keean / zenscript

A trait based language that compiles to JavaScript
MIT License
42 stars 7 forks source link

Usage Instructions #20

Open keean opened 7 years ago

keean commented 7 years ago

I will keep this top-post up to date. Starting with a program in a file ending '.zs':

let id2 = (x) =>
    let id = (x) => x
    let y = id(x)
    return y
id2(42)

Compile using:

node src/compiler.js t1.zs

This will output a JavaScript file called t1.js

var id2=function (x){var id=function (x){return x;};var y=id(x);return y;};id2(42);

and dump the AST into t1.ast.

{
  "status": true,
  "value": {
    "blk": [
      {
        "decl": "id2",
        "exp": {
          "fn": "",
          "args": [
            "x"
          ],
          "body": {
            "blk": [
              {
                "decl": "id",
                "exp": {
                  "fn": "",
                  "args": [
                    "x"
                  ],
                  "body": {
                    "rtn": {
                      "var": "x"
                    }
                  }
                }
              },
              {
                "decl": "y",
                "exp": {
                  "app": "id",
                  "args": [
                    {
                      "var": "x"
                    }
                  ]
                }
              },
              {
                "rtn": {
                  "var": "y"
                }
              }
            ]
          }
        }
      },
      {
        "app": "id2",
        "args": [
          {
            "lit": 42
          }
        ]
      }
    ]
  }
}

You can then evaluate the program using:

node src/eval.js t1.js

This program should return:

42
shelby3 commented 7 years ago

@keean wrote:

 let id2 = (x) =>
    let id = (x) => x
    let y = id(x)
    return y

You don't need to use return there in our grammar, because the body of the function is an expression that has the value and type its last expression. The return should never be used except where it is short-circuiting, and our parser should give an error when it is used where it shouldn't be.

Also we changed the grammar to remove the let on function definitions. And I current have the grammar such that you can't assign an inline (anonymous or not) function. I should probably change that to only disallowing assignment on let references, not on var references.

There is no way we can design a grammar between one or more people with parser combinators in code as to the record of what is decided.

shelby3 commented 7 years ago

@keean wrote:

and dump the AST into t1.ast.

{
  "status": true,
  "value": {
    "blk": [
      {
        "decl": "id2",
        "exp": {
          "fn": "",
          "args": [
            "x"
          ],
          "body": {
            "blk": [
              {
                "decl": "id",
                "exp": {
                  "fn": "",
                  "args": [
                    "x"
                  ],
                  "body": {
                    "rtn": {
                      "var": "x"
                    }
                  }
                }
              },
              {
                "decl": "y",
                "exp": {
                  "app": "id",
                  "args": [
                    {
                      "var": "x"
                    }
                  ]
                }
              },
              {
                "rtn": {
                  "var": "y"
                }
              }
            ]
          }
        }
      },
      {
        "app": "id2",
        "args": [
          {
            "lit": 42
          }
        ]
      }
    ]
  }
}

I'd much rather that displayed as the data type constructor function, than as "string" named record objects. Wouldn't be much easier to read and correspond with code, if we write code with data types instead of parser combinators.

keean commented 7 years ago

Whether you the AST is constructed with anonymous objects, or objects with a prototype has nothing to do with whether we use parser combinators or not.

I am experimenting with restructuring the code around AST prototypes at the moment, but I know from experience the Object Oriented approach to compiler building results in massive amounts of boilerplate.

shelby3 commented 7 years ago

@keean wrote:

I know from experience the Object Oriented approach to compiler building results in massive amounts of boilerplate.

I wish you could provide an example to help me see why.

And I thought I was suggesting data types, not OOP subclassing.

keean commented 7 years ago

And I thought I was suggesting data types, not OOP subclassing.

Sorry my mistake I misinterpreted what you were saying. I think that can work, it would just have to use instanceof in for matching nodes, and I think it would be better, although it would add some extra code.