Giter Site home page Giter Site logo

mumuki / mulang Goto Github PK

View Code? Open in Web Editor NEW
124.0 12.0 9.0 15.9 MB

:bamboo: Universal, Multi Language, Multi Paradigm code analyzer

Home Page: https://mumuki.github.io/mulang

License: GNU General Public License v3.0

Haskell 78.35% Shell 0.90% Ruby 10.23% HTML 0.02% JavaScript 8.86% Yacc 0.95% Lex 0.68%
mumuki code-analysis ast haskell static-analysis inspection languages educational mulang-ast functional

mulang's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

mulang's Issues

Update to GHC 8

GHC 8 has very nice features, like custom pattern - pattern aliases, which would probably improve a lot of our pattern matching code.

For example, instead of doing

doSomethingWithBody p@(ProcedureDeclaration _ _) = f . simpleProcedureBody $ p

we could do the following:

doSomethingWithBody (SimpleProcedureDeclaration _ _ body) = f body

Add smell checks for collections handling

There are some frequent errors in collection usages. For example, getting the length of the result of a map - the map is meaningless.

We should think better about those scenarios and implement checks for them

Pattern matching expectations

We need expectations that checks for the presence of pattern matching in a functional equation

Pattern matching occurs when when any of the clauses of a functions contains a pattern that is not a variable pattern:

foo (x:_) = True

Add parses inspection

Add an inspection that tells whether an expression is the result of parsing a given piece of code.

Such expressions allows to:

  • check for a unique solution
  • check that a solution is different to another

Error running expectations of gobstones procedure

It returns mulang: Maybe.fromJust: Nothing.

Original code:

procedure MoverSegunBolitas() {
  if (nroBolitas(Azul) + nroBolitas(Negro) + nroBolitas(Rojo) + nroBolitas(Verde) > 10) {
    Mover(Este)
  } else {
    Mover(Norte)
  }
}

AST:

➜ echo "procedure MoverSegunBolitas() {\n  if (nroBolitas(Azul) + nroBolitas(Negro) + nroBolitas(Rojo) + nroBolitas(Verde) > 10) {\n    Mover(Este)\n  }\nelse {\n    Mover(Norte)\n  }\n }" | rungs
[
  {
    "name": "MoverSegunBolitas",
    "arity": "routine",
    "alias": "procedureDeclaration",
    "parameters": [],
    "body": [
      {
        "alias": "if",
        "condition": {
          "alias": "GraterOperation",
          "left": {
            "alias": "SumOperation",
            "left": {
              "alias": "SumOperation",
              "left": {
                "alias": "SumOperation",
                "left": {
                  "arity": "binary",
                  "alias": "numStones",
                  "parameters": [
                    {
                      "value": 0,
                      "alias": "Blue"
                    }
                  ]
                },
                "right": {
                  "arity": "binary",
                  "alias": "numStones",
                  "parameters": [
                    {
                      "value": 2,
                      "alias": "Black"
                    }
                  ]
                },
                "arity": "binary"
              },
              "right": {
                "arity": "binary",
                "alias": "numStones",
                "parameters": [
                  {
                    "value": 1,
                    "alias": "Red"
                  }
                ]
              },
              "arity": "binary"
            },
            "right": {
              "arity": "binary",
              "alias": "numStones",
              "parameters": [
                {
                  "value": 3,
                  "alias": "Green"
                }
              ]
            },
            "arity": "binary"
          },
          "right": {
            "value": 10,
            "alias": "NumericLiteral"
          },
          "arity": "binary"
        },
        "trueBranch": [
          {
            "arity": "statement",
            "alias": "MoveClaw",
            "parameters": [
              {
                "value": [
                  1,
                  0
                ],
                "alias": "East"
              }
            ]
          }
        ],
        "falseBranch": [
          {
            "arity": "statement",
            "alias": "MoveClaw",
            "parameters": [
              {
                "value": [
                  0,
                  1
                ],
                "alias": "North"
              }
            ]
          }
        ]
      }
    ]
  }
]

Mulang command:

./mulang '{                                       
      "expectations":[{
                "tag":"Basic",
                "binding":"x",
                "inspection":"HasBiniding"}],
        "code": {
            "content":"procedure MoverSegunBolitas() {\n  if (nroBolitas(Azul) + nroBolitas(Negro) + nroBolitas(Rojo) + nroBolitas(Verde) > 10) {\n    Mover(Este)\n  }\nelse {\n    Mover(Norte)\n  }\n }",
            "language":"GobstonesAst"}
  }'

mulang: Maybe.fromJust: Nothing

Add InheritsFrom inspection

Add support for InheritsFrom inspection - e.g.:

  • Reactor Not:InheritsFrom:List: class Reactor must not inherit from List
  • InheritsFrom:List: there must be a class that inherits from from List
  • InheritsFrom:^Person: there must be a class that is not a Person

Also we could add UsesInheritance, to check that a class declaration indicates superclass.

Error al crear listas infinitas

Ejercicio: La historia sin fin

Solución:

infinitosUnos = 1:infinitosUnos

u otra solución:

infinitosUnos = [1,1..]

Estado: errored

See http://algo2-undav.mumuki.io/guides/pdep-utn/mumuki-guia-funcional-recursividad

Error completo:

Invalid JSON :
A JSON text must at least contain two octets!:


/var/lib/gems/2.0.0/gems/mumukit-core-0.1.3/lib/mumukit/core/json.rb:7:in rescue in pretty_parse' /var/lib/gems/2.0.0/gems/mumukit-core-0.1.3/lib/mumukit/core/json.rb:5:inpretty_parse'
/var/lib/gems/2.0.0/gems/mumukit-2.5.0/lib/mumukit/templates/mulang_expectations_hook.rb:16:in post_process_file' /var/lib/gems/2.0.0/gems/mumukit-2.5.0/lib/mumukit/templates/file_hook.rb:11:inrun!'
/var/lib/gems/2.0.0/gems/mumukit-2.5.0/lib/mumukit/server/test_server.rb:86:in compile_and_run' /var/lib/gems/2.0.0/gems/mumukit-2.5.0/lib/mumukit/server/test_server.rb:72:inrun_expectations!'
/var/lib/gems/2.0.0/gems/mumukit-2.5.0/lib/mumukit/server/test_server.rb:36:in block in test!' /var/lib/gems/2.0.0/gems/mumukit-2.5.0/lib/mumukit/server/test_server.rb:111:inrespond_to'
/var/lib/gems/2.0.0/gems/mumukit-2.5.0/lib/mumukit/server/test_server.rb:34:in test!' /var/lib/gems/2.0.0/gems/mumukit-2.5.0/lib/mumukit/server/app.rb:51:inblock in class:App'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1611:in call' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1611:inblock in compile!'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:975:in []' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:975:inblock (3 levels) in route!'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:994:in route_eval' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:975:inblock (2 levels) in route!'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1015:in block in process_route' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1013:incatch'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1013:in process_route' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:973:inblock in route!'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:972:in each' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:972:inroute!'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1085:in block in dispatch!' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1067:inblock in invoke'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1067:in catch' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1067:ininvoke'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1082:in dispatch!' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:907:inblock in call!'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1067:in block in invoke' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1067:incatch'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1067:in invoke' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:907:incall!'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:895:in call' /var/lib/gems/2.0.0/gems/rack-protection-1.5.3/lib/rack/protection/xss_header.rb:18:incall'
/var/lib/gems/2.0.0/gems/rack-protection-1.5.3/lib/rack/protection/path_traversal.rb:16:in call' /var/lib/gems/2.0.0/gems/rack-protection-1.5.3/lib/rack/protection/json_csrf.rb:18:incall'
/var/lib/gems/2.0.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:in call' /var/lib/gems/2.0.0/gems/rack-protection-1.5.3/lib/rack/protection/base.rb:49:incall'
/var/lib/gems/2.0.0/gems/rack-protection-1.5.3/lib/rack/protection/frame_options.rb:31:in call' /var/lib/gems/2.0.0/gems/rack-1.6.4/lib/rack/logger.rb:15:incall'
/var/lib/gems/2.0.0/gems/rack-1.6.4/lib/rack/commonlogger.rb:33:in call' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:219:incall'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:212:in call' /var/lib/gems/2.0.0/gems/rack-1.6.4/lib/rack/head.rb:13:incall'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/show_exceptions.rb:25:in call' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:182:incall'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:2013:in call' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1487:inblock in call'
/var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1787:in synchronize' /var/lib/gems/2.0.0/gems/sinatra-1.4.7/lib/sinatra/base.rb:1487:incall'
/var/lib/gems/2.0.0/gems/puma-3.6.0/lib/puma/configuration.rb:225:in call' /var/lib/gems/2.0.0/gems/puma-3.6.0/lib/puma/server.rb:578:inhandle_request'
/var/lib/gems/2.0.0/gems/puma-3.6.0/lib/puma/server.rb:415:in process_client' /var/lib/gems/2.0.0/gems/puma-3.6.0/lib/puma/server.rb:275:inblock in run'
/var/lib/gems/2.0.0/gems/puma-3.6.0/lib/puma/thread_pool.rb:116:in call' /var/lib/gems/2.0.0/gems/puma-3.6.0/lib/puma/thread_pool.rb:116:inblock in spawn_thread'

HasUsage inspection fails when the function is part of a parameter of a higher order function

From issue mumuki/mumuki-laboratory#514

Suppose the expectation for f is HasUsage:g, the following solutions for f pass the expectation

f list x = elem (g x) list
f list = flip elem list.g
f list x= any (\y -> y == g x) list

But these ones (and similar where g is applied as part of the parameter of a higher order function) do not, and end up stating g is not used:

f list x= any (== g x) list
f list x= ((>0).length.filter (== g x)) list

Inspection for counting clauses or equations

We need two inspections for checking that a computation has N clauses or equations:

  • declaresWithEquationsCount

  • declaresWithClausesCount

    It should be similar in type signature to declaresWithArity:

Expressiveness smells

Add smell detection for expressiveness:

  • used token should be full words in the target human language
  • used tokens should "long enough": more than, say, 3 chars long.
  • tokens should not be common meaningless terms, like tmp, x, foo, manager, and so on

Perhaps we should be able to deactive such smells detection sometimes.

Prolog parser

Our next goal should be implement a Mulang parser for Prolog, since it is very simple and lets us test logic expectations

Repeated code smells

We should be able to check for common patterns of logic duplication: similar functions, predicates, identical consult pairs, and so on.

Allow mulang to generate signatures

It would be nice if mulang could support signatures generation. For example, given the following haskell code:

foo :: Int -> Int
foo x = x + 1

It should produce

  • [TypedSignature "foo" ["Int"] "Int"]
  • or even foo :: Int -> Int

And given the following Prolog code:

foo(X, X).
foo(X, Y) :- bar(Y).

It should produce

  • [UntypedSignature "foo" 2]
  • or even foo/2

ANTLR integration

It would really speed up process of adding native languages support if ANTLR - for which there are dozens of popular languages grammars https://github.com/antlr/grammars-v4 - could generate Haskell an AST encoded in data's.

We should investigate about that

Extend object orientation support

Add support for classes, interfaces and mixins declarations, and checks about them:

  • declaresClass
  • declaresMixin
  • declaresInterface
  • inheritsFromClass
  • includesMixin
  • implementsInterface
  • associatesWith

Also, declares should be extended to support them

Move to stack

We should consider moving to stack, which is getting a de-facto standard.

Support logic programming expectations

They should include:

  • hasNegation - it could also work for functional and imperative languages
  • hasForAll - checks if a universal quantifier exists
  • hasFindall - I actually don't like that name...

Update JS parser version

We should move to the latest 0.6 language.javascript package, since it contains a much simpler and easy-to-maintain JavaScript AST.

Combiner for counting matches of expressions

We need two other combiners that allows to count the number of matches of a given Inspection:

  • countAtLeast :: Int -> Inspection -> Inspection
  • countAtMost :: Int -> Inspection -> Inspection

Both combiners should count them lazily.

Introducing this combiner may need a refactor that splits the current inspector functions into a core function and containsExpression

Mulang crashes with non ASCII charateres

See

franco@xinaiu:~/tmp/mumuki/mulang$ ./dist/build/mulang/mulang '{                                
      "expectations":[{                    
                "tag":"Basic",           
                "binding":"x",           
                "inspection":"HasBinding"}],       
        "code": {                          
            "content":"x = \"¡\"",           
            "language":"Haskell"}        
  }'
mulang: "Error in $: Failed reading: Cannot decode byte '\\xa1': Data.Text.Internal.Encoding.decodeUtf8: Invalid UTF-8 stream"

Generate language-sensitive code signatures

For example, it would be nice that C-like languages produce the following code for a typed signature:

foo(A, B)

While haskell-like languages, produce the following code:

foo :: A -> B

Improve reporting of parsing errors

Improve reporting of parsing errors: return an especial analysis result instead of returning an empty json, something like the following:

data AnalysisResult = SuccessfullAnalysis {
                        expectationResults :: [ExpectationResult],
                        detectedSmells :: [Expectation], 
                        signatures :: [Code]  }
                    | FailedAnalysis String

Imperative expectations

We need more expectations and support for imperative languages.

  • usesSwitch
  • usesFor
  • declaresProcedure
  • declaresRecord

@faloi please suggest here what you need for Gobstones

Wrong expectation

With this code...
esBisiesto anio = ((|| (cond2 anio)).cond1) anio

Throw...
esBisiesto tiene parámetros innecesarios (se pueden eliminar mediante point-free)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.