From 27093064a9ca4baa9e2aec73fb04ba547981f49e Mon Sep 17 00:00:00 2001 From: ncannasse Date: Tue, 18 Sep 2018 16:15:15 +0200 Subject: [PATCH] added ECheckType, added short lambda parsing --- .vscode/launch.json | 16 ++++++++++++ .vscode/tasks.json | 16 ++++++++++++ Test.hx | 6 +++++ hscript.hxml | 3 ++- hscript/Bytes.hx | 4 +++ hscript/Expr.hx | 1 + hscript/Interp.hx | 2 ++ hscript/Macro.hx | 2 ++ hscript/Parser.hx | 61 +++++++++++++++++++++++++++++++++++++++++++-- hscript/Printer.hx | 6 +++++ hscript/Tools.hx | 2 ++ 11 files changed, 116 insertions(+), 3 deletions(-) create mode 100644 .vscode/launch.json create mode 100644 .vscode/tasks.json diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..c65cb6a --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,16 @@ +{ + // Utilisez IntelliSense pour en savoir plus sur les attributs possibles. + // Pointez pour afficher la description des attributs existants. + // Pour plus d'informations, visitez : https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "name": "HashLink (launch)", + "request": "launch", + "type": "hl", + "hxml": "hscript.hxml", + "cwd": "${workspaceRoot}", + "preLaunchTask": "Build" + } + ] +} \ No newline at end of file diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..0d772d5 --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,16 @@ +{ + // See https://go.microsoft.com/fwlink/?LinkId=733558 + // for the documentation about the tasks.json format + "version": "2.0.0", + "tasks": [ + { + "label": "Build", + "type": "hxml", + "file": "hscript.hxml", + "group": { + "kind": "build", + "isDefault": true + } + } + ] +} \ No newline at end of file diff --git a/Test.hx b/Test.hx index 15e7e29..ea5962a 100644 --- a/Test.hx +++ b/Test.hx @@ -99,6 +99,12 @@ class Test extends TestCase { assertScript("var a:Array=[1,2,4]; a[2]", 4, null, true); assertScript("/**/0", 0); assertScript("x=1;x*=-2", -2); + assertScript("var f = x -> x + 1; f(3)", 4); + assertScript("var f = (x) -> x + 1; f(3)", 4); + assertScript("var f = (x:Int) -> x + 1; f(3)", 4); + assertScript("var f = (x,y) -> x + y; f(3,1)", 4); + assertScript("var f = (x,y:Int) -> x + y; f(3,1)", 4); + assertScript("var f = (x:Int,y:Int) -> x + y; f(3,1)", 4); } function testMap():Void { diff --git a/hscript.hxml b/hscript.hxml index 7c62986..e9f3c44 100644 --- a/hscript.hxml +++ b/hscript.hxml @@ -1 +1,2 @@ -bin/build-flash.hxml \ No newline at end of file +bin/build-each.hxml +-hl bin/Test.hl \ No newline at end of file diff --git a/hscript/Bytes.hx b/hscript/Bytes.hx index 149e800..066c12f 100644 --- a/hscript/Bytes.hx +++ b/hscript/Bytes.hx @@ -246,6 +246,8 @@ class Bytes { bout.addByte(args == null ? 0 : args.length + 1); if( args != null ) for( e in args ) doEncode(e); doEncode(e); + case ECheckType(e,_): + doEncode(e); } } @@ -374,6 +376,8 @@ class Bytes { var count = bin.get(pin++); var args = count == 0 ? null : [for( i in 0...count - 1 ) doDecode()]; EMeta(name, args, doDecode()); + case 26: + ECheckType(doDecode(), CTPath(["Void"])); case 255: null; default: diff --git a/hscript/Expr.hx b/hscript/Expr.hx index d6d81d8..f949fb9 100644 --- a/hscript/Expr.hx +++ b/hscript/Expr.hx @@ -68,6 +68,7 @@ enum Expr { ESwitch( e : Expr, cases : Array<{ values : Array, expr : Expr }>, ?defaultExpr : Expr); EDoWhile( cond : Expr, e : Expr); EMeta( name : String, args : Array, e : Expr ); + ECheckType( e : Expr, t : CType ); } typedef Argument = { name : String, ?t : CType, ?opt : Bool, ?value : Expr }; diff --git a/hscript/Interp.hx b/hscript/Interp.hx index 75e0d8c..b8a81c4 100644 --- a/hscript/Interp.hx +++ b/hscript/Interp.hx @@ -574,6 +574,8 @@ class Interp { return val; case EMeta(_, _, e): return expr(e); + case ECheckType(e,_): + return expr(e); } return null; } diff --git a/hscript/Macro.hx b/hscript/Macro.hx index f09d661..6a7125f 100644 --- a/hscript/Macro.hx +++ b/hscript/Macro.hx @@ -238,6 +238,8 @@ class Macro { case EMeta(m, params, esub): var mpos = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end; EMeta({ name : m, params : params == null ? [] : [for( p in params ) convert(p)], pos : mpos }, convert(esub)); + case ECheckType(e, t): + ECheckType(convert(e), convertType(t)); }, pos : #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end } } diff --git a/hscript/Parser.hx b/hscript/Parser.hx index 524c88b..10e5646 100644 --- a/hscript/Parser.hx +++ b/hscript/Parser.hx @@ -359,8 +359,31 @@ class Parser { return parseExprNext(mk(EConst(c))); case TPOpen: var e = parseExpr(); - ensure(TPClose); - return parseExprNext(mk(EParent(e),p1,tokenMax)); + tk = token(); + switch( tk ) { + case TPClose: + return parseExprNext(mk(EParent(e),p1,tokenMax)); + case TDoubleDot: + var t = parseType(); + tk = token(); + switch( tk ) { + case TPClose: + return parseExprNext(mk(ECheckType(e,t),p1,tokenMax)); + case TComma: + switch( expr(e) ) { + case EIdent(v): return parseLambda([{ name : v, t : t }], pmin(e)); + default: + } + default: + } + case TComma: + switch( expr(e) ) { + case EIdent(v): return parseLambda([{name:v}], pmin(e)); + default: + } + default: + } + return unexpected(tk); case TBrOpen: tk = token(); switch( tk ) { @@ -450,6 +473,25 @@ class Parser { } } + function parseLambda( args : Array, pmin ) { + while( true ) { + var id = getIdent(); + var t = maybe(TDoubleDot) ? parseType() : null; + args.push({ name : id, t : t }); + var tk = token(); + switch( tk ) { + case TComma: + case TPClose: + break; + default: + unexpected(tk); + } + } + ensureToken(TOp("->")); + var eret = parseExpr(); + return mk(EFunction(args, mk(EReturn(eret),pmin)), pmin); + } + function parseMetaArgs() { var tk = token(); if( tk != TPOpen ) { @@ -709,6 +751,21 @@ class Parser { var tk = token(); switch( tk ) { case TOp(op): + + if( op == "->" ) { + // single arg reinterpretation of `f -> e` , `(f) -> e` and `(f:T) -> e` + switch( expr(e1) ) { + case EIdent(i), EParent(expr(_) => EIdent(i)): + var eret = parseExpr(); + return mk(EFunction([{ name : i }], mk(EReturn(eret),pmin(eret))), pmin(e1)); + case ECheckType(expr(_) => EIdent(i), t): + var eret = parseExpr(); + return mk(EFunction([{ name : i, t : t }], mk(EReturn(eret),pmin(eret))), pmin(e1)); + default: + } + unexpected(tk); + } + if( unops.get(op) ) { if( isBlock(e1) || switch(expr(e1)) { case EParent(_): true; default: false; } ) { push(tk); diff --git a/hscript/Printer.hx b/hscript/Printer.hx index 7b776c4..8bd1c47 100644 --- a/hscript/Printer.hx +++ b/hscript/Printer.hx @@ -300,6 +300,12 @@ class Printer { } add(" "); expr(e); + case ECheckType(e, t): + add("("); + expr(e); + add(" : "); + addType(t); + add(")"); } } diff --git a/hscript/Tools.hx b/hscript/Tools.hx index 04c39b5..c1b554a 100644 --- a/hscript/Tools.hx +++ b/hscript/Tools.hx @@ -56,6 +56,7 @@ class Tools { } if( def != null ) f(def); case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e); + case ECheckType(e,_): f(e); } } @@ -88,6 +89,7 @@ class Tools { case ETernary(c, e1, e2): ETernary(f(c), f(e1), f(e2)); case ESwitch(e, cases, def): ESwitch(f(e), [for( c in cases ) { values : [for( v in c.values ) f(v)], expr : f(c.expr) } ], def == null ? null : f(def)); case EMeta(name, args, e): EMeta(name, args == null ? null : [for( a in args ) f(a)], f(e)); + case ECheckType(e,t): ECheckType(f(e), t); } #if hscriptPos return { e : edef, pmin : e.pmin, pmax : e.pmax, origin : e.origin, line : e.line };