added possible type declarations (with Parser.allowTypes)
This commit is contained in:
+1
-2
@@ -1,5 +1,4 @@
|
||||
-swf hscript.swf
|
||||
-swf-version 9
|
||||
-swf9 hscript.swf
|
||||
-swf-header 800:600:30:FFFFFF
|
||||
--flash-strict
|
||||
-main Test
|
||||
|
||||
+8
-1
@@ -37,7 +37,14 @@
|
||||
</library>
|
||||
<!-- Paths to exclude from the Project Explorer tree -->
|
||||
<hiddenPaths>
|
||||
<!-- example: <hidden path="..." /> -->
|
||||
<hidden path="haxelib.xml" />
|
||||
<hidden path="hscript.hxml" />
|
||||
<hidden path="hscript.js" />
|
||||
<hidden path="hscript.n" />
|
||||
<hidden path="hscript.swf" />
|
||||
<hidden path="hscript9.swf" />
|
||||
<hidden path="release.bat" />
|
||||
<hidden path="release.zip" />
|
||||
</hiddenPaths>
|
||||
<!-- Executed before build -->
|
||||
<preBuildCommand />
|
||||
|
||||
+7
-7
@@ -132,7 +132,7 @@ class Bytes {
|
||||
doEncodeConst(c);
|
||||
case EIdent(v):
|
||||
doEncodeString(v);
|
||||
case EVar(n,e):
|
||||
case EVar(n,_,e):
|
||||
doEncodeString(n);
|
||||
if( e == null )
|
||||
bout.addByte(255);
|
||||
@@ -175,10 +175,10 @@ class Bytes {
|
||||
doEncode(it);
|
||||
doEncode(e);
|
||||
case EBreak, EContinue:
|
||||
case EFunction(params,e,name):
|
||||
case EFunction(params,e,name,_):
|
||||
bout.addByte(params.length);
|
||||
for( p in params )
|
||||
doEncodeString(p);
|
||||
doEncodeString(p.name);
|
||||
doEncode(e);
|
||||
doEncodeString(name == null?"":name);
|
||||
case EReturn(e):
|
||||
@@ -201,7 +201,7 @@ class Bytes {
|
||||
doEncode(e);
|
||||
case EThrow(e):
|
||||
doEncode(e);
|
||||
case ETry(e,v,ecatch):
|
||||
case ETry(e,v,_,ecatch):
|
||||
doEncode(e);
|
||||
doEncodeString(v);
|
||||
doEncode(ecatch);
|
||||
@@ -214,7 +214,7 @@ class Bytes {
|
||||
}
|
||||
}
|
||||
|
||||
function doDecode() {
|
||||
function doDecode() : Expr {
|
||||
return switch( bin.get(pin++) ) {
|
||||
case 0:
|
||||
EConst( doDecodeConst() );
|
||||
@@ -265,7 +265,7 @@ class Bytes {
|
||||
case 14:
|
||||
var params = new Array();
|
||||
for( i in 0...bin.get(pin++) )
|
||||
params.push(doDecodeString());
|
||||
params.push({ name : doDecodeString(), t : null });
|
||||
var e = doDecode();
|
||||
var name = doDecodeString();
|
||||
EFunction(params,e,(name == "") ? null: name);
|
||||
@@ -290,7 +290,7 @@ class Bytes {
|
||||
case 20:
|
||||
var e = doDecode();
|
||||
var v = doDecodeString();
|
||||
ETry(e,v,doDecode());
|
||||
ETry(e,v,null,doDecode());
|
||||
case 21:
|
||||
var fl = new Array();
|
||||
for( i in 0...bin.get(pin++) ) {
|
||||
|
||||
+10
-3
@@ -34,7 +34,7 @@ enum Const {
|
||||
enum Expr {
|
||||
EConst( c : Const );
|
||||
EIdent( v : String );
|
||||
EVar( n : String, ?e : Expr );
|
||||
EVar( n : String, ?t : CType, ?e : Expr );
|
||||
EParent( e : Expr );
|
||||
EBlock( e : Array<Expr> );
|
||||
EField( e : Expr, f : String );
|
||||
@@ -46,16 +46,23 @@ enum Expr {
|
||||
EFor( v : String, it : Expr, e : Expr );
|
||||
EBreak;
|
||||
EContinue;
|
||||
EFunction( params : Array<String>, e : Expr, ?name : String );
|
||||
EFunction( args : Array<{ name : String, t : Null<CType> }>, e : Expr, ?name : String, ?ret : CType );
|
||||
EReturn( ?e : Expr );
|
||||
EArray( e : Expr, index : Expr );
|
||||
EArrayDecl( e : Array<Expr> );
|
||||
ENew( cl : String, params : Array<Expr> );
|
||||
EThrow( e : Expr );
|
||||
ETry( e : Expr, v : String, ecatch : Expr );
|
||||
ETry( e : Expr, v : String, t : Null<CType>, ecatch : Expr );
|
||||
EObject( fl : Array<{ name : String, e : Expr }> );
|
||||
}
|
||||
|
||||
enum CType {
|
||||
CTPath( path : Array<String>, ?params : Array<CType> );
|
||||
CTFun( args : Array<CType>, ret : CType );
|
||||
CTAnon( fields : Array<{ name : String, t : CType }> );
|
||||
CTParent( t : CType );
|
||||
}
|
||||
|
||||
enum Error {
|
||||
EInvalidChar( c : Int );
|
||||
EUnexpected( s : String );
|
||||
|
||||
+4
-4
@@ -218,7 +218,7 @@ class Interp {
|
||||
if( v == null && !variables.exists(id) )
|
||||
throw Error.EUnknownVariable(id);
|
||||
return v;
|
||||
case EVar(n,e):
|
||||
case EVar(n,_,e):
|
||||
declared.push({ n : n, old : locals.get(n) });
|
||||
locals.set(n,{ r : (e == null)?null:expr(e) });
|
||||
return null;
|
||||
@@ -282,7 +282,7 @@ class Interp {
|
||||
throw SContinue;
|
||||
case EReturn(e):
|
||||
throw SReturn((e == null)?null:expr(e));
|
||||
case EFunction(params,fexpr,name):
|
||||
case EFunction(params,fexpr,name,_):
|
||||
var capturedLocals = duplicate(locals);
|
||||
var me = this;
|
||||
var f = function(args:Array<Dynamic>) {
|
||||
@@ -290,7 +290,7 @@ class Interp {
|
||||
var old = me.locals;
|
||||
me.locals = me.duplicate(capturedLocals);
|
||||
for( i in 0...params.length )
|
||||
me.locals.set(params[i],{ r : args[i] });
|
||||
me.locals.set(params[i].name,{ r : args[i] });
|
||||
var r = null;
|
||||
try {
|
||||
r = me.exprReturn(fexpr);
|
||||
@@ -323,7 +323,7 @@ class Interp {
|
||||
return cnew(cl,a);
|
||||
case EThrow(e):
|
||||
throw expr(e);
|
||||
case ETry(e,n,ecatch):
|
||||
case ETry(e,n,_,ecatch):
|
||||
var old = declared.length;
|
||||
try {
|
||||
var v : Dynamic = expr(e);
|
||||
|
||||
+165
-47
@@ -57,6 +57,11 @@ class Parser {
|
||||
activate JSON compatiblity
|
||||
**/
|
||||
public var allowJSON : Bool;
|
||||
|
||||
/**
|
||||
allow types declarations
|
||||
**/
|
||||
public var allowTypes : Bool;
|
||||
|
||||
// implementation
|
||||
var input : haxe.io.Input;
|
||||
@@ -103,7 +108,7 @@ class Parser {
|
||||
while( true ) {
|
||||
var tk = token();
|
||||
if( tk == TEof ) break;
|
||||
tokens.add(tk);
|
||||
push(tk);
|
||||
a.push(parseFullExpr());
|
||||
}
|
||||
return if( a.length == 1 ) a[0] else EBlock(a);
|
||||
@@ -113,12 +118,21 @@ class Parser {
|
||||
throw Error.EUnexpected(tokenString(tk));
|
||||
return null;
|
||||
}
|
||||
|
||||
inline function push(tk) {
|
||||
tokens.add(tk);
|
||||
}
|
||||
|
||||
inline function ensure(tk) {
|
||||
var t = token();
|
||||
if( t != tk ) unexpected(t);
|
||||
}
|
||||
|
||||
function isBlock(e) {
|
||||
return switch( e ) {
|
||||
case EBlock(_), EObject(_): true;
|
||||
case EFunction(_,e,_): isBlock(e);
|
||||
case EVar(_,e): e != null && isBlock(e);
|
||||
case EFunction(_,e,_,_): isBlock(e);
|
||||
case EVar(_,_,e): e != null && isBlock(e);
|
||||
case EIf(_,e1,e2): if( e2 != null ) isBlock(e2) else isBlock(e1);
|
||||
case EBinop(_,_,e): isBlock(e);
|
||||
case EUnop(_,prefix,e): !prefix && isBlock(e);
|
||||
@@ -134,7 +148,7 @@ class Parser {
|
||||
var tk = token();
|
||||
if( tk != TSemicolon && tk != TEof ) {
|
||||
if( isBlock(e) )
|
||||
tokens.add(tk);
|
||||
push(tk);
|
||||
else
|
||||
unexpected(tk);
|
||||
}
|
||||
@@ -161,8 +175,7 @@ class Parser {
|
||||
default:
|
||||
unexpected(tk);
|
||||
}
|
||||
tk = token();
|
||||
if( tk != TDoubleDot ) unexpected(tk);
|
||||
ensure(TDoubleDot);
|
||||
fl.push({ name : id, e : parseExpr() });
|
||||
tk = token();
|
||||
switch( tk ) {
|
||||
@@ -188,8 +201,7 @@ class Parser {
|
||||
return parseExprNext(EConst(c));
|
||||
case TPOpen:
|
||||
var e = parseExpr();
|
||||
tk = token();
|
||||
if( tk != TPClose ) unexpected(tk);
|
||||
ensure(TPClose);
|
||||
return parseExprNext(EParent(e));
|
||||
case TBrOpen:
|
||||
tk = token();
|
||||
@@ -198,8 +210,8 @@ class Parser {
|
||||
return parseExprNext(EObject([]));
|
||||
case TId(id):
|
||||
var tk2 = token();
|
||||
tokens.add(tk2);
|
||||
tokens.add(tk);
|
||||
push(tk2);
|
||||
push(tk);
|
||||
switch( tk2 ) {
|
||||
case TDoubleDot:
|
||||
return parseExprNext(parseObject());
|
||||
@@ -210,20 +222,20 @@ class Parser {
|
||||
switch( c ) {
|
||||
case CString(_):
|
||||
var tk2 = token();
|
||||
tokens.add(tk2);
|
||||
tokens.add(tk);
|
||||
push(tk2);
|
||||
push(tk);
|
||||
switch( tk2 ) {
|
||||
case TDoubleDot:
|
||||
return parseExprNext(parseObject());
|
||||
default:
|
||||
}
|
||||
default:
|
||||
tokens.add(tk);
|
||||
push(tk);
|
||||
}
|
||||
} else
|
||||
tokens.add(tk);
|
||||
push(tk);
|
||||
default:
|
||||
tokens.add(tk);
|
||||
push(tk);
|
||||
}
|
||||
var a = new Array();
|
||||
while( true ) {
|
||||
@@ -231,7 +243,7 @@ class Parser {
|
||||
tk = token();
|
||||
if( tk == TBrClose )
|
||||
break;
|
||||
tokens.add(tk);
|
||||
push(tk);
|
||||
}
|
||||
return EBlock(a);
|
||||
case TOp(op):
|
||||
@@ -244,7 +256,7 @@ class Parser {
|
||||
var a = new Array();
|
||||
tk = token();
|
||||
while( tk != TBkClose ) {
|
||||
tokens.add(tk);
|
||||
push(tk);
|
||||
a.push(parseExpr());
|
||||
tk = token();
|
||||
if( tk == TComma )
|
||||
@@ -296,8 +308,8 @@ class Parser {
|
||||
if( Type.enumEq(tk,TId("else")) )
|
||||
e2 = parseExpr();
|
||||
else {
|
||||
tokens.add(tk);
|
||||
if( semic ) tokens.add(TSemicolon);
|
||||
push(tk);
|
||||
if( semic ) push(TSemicolon);
|
||||
}
|
||||
EIf(cond,e1,e2);
|
||||
case "var":
|
||||
@@ -308,20 +320,24 @@ class Parser {
|
||||
default: unexpected(tk);
|
||||
}
|
||||
tk = token();
|
||||
var t = null;
|
||||
if( tk == TDoubleDot && allowTypes ) {
|
||||
t = parseType();
|
||||
tk = token();
|
||||
}
|
||||
var e = null;
|
||||
if( Type.enumEq(tk,TOp("=")) )
|
||||
e = parseExpr();
|
||||
else
|
||||
tokens.add(tk);
|
||||
EVar(ident,e);
|
||||
push(tk);
|
||||
EVar(ident,t,e);
|
||||
case "while":
|
||||
var econd = parseExpr();
|
||||
var e = parseExpr();
|
||||
EWhile(econd,e);
|
||||
case "for":
|
||||
ensure(TPOpen);
|
||||
var tk = token();
|
||||
if( tk != TPOpen ) unexpected(tk);
|
||||
tk = token();
|
||||
var vname = null;
|
||||
switch( tk ) {
|
||||
case TId(id): vname = id;
|
||||
@@ -330,8 +346,7 @@ class Parser {
|
||||
tk = token();
|
||||
if( !Type.enumEq(tk,TId("in")) ) unexpected(tk);
|
||||
var eiter = parseExpr();
|
||||
tk = token();
|
||||
if( tk != TPClose ) unexpected(tk);
|
||||
ensure(TPClose);
|
||||
EFor(vname,eiter,parseExpr());
|
||||
case "break": EBreak;
|
||||
case "continue": EContinue;
|
||||
@@ -340,19 +355,26 @@ class Parser {
|
||||
var tk = token();
|
||||
var name = null;
|
||||
switch( tk ) {
|
||||
case TId(id): name = id; tk = token();
|
||||
default:
|
||||
case TId(id): name = id;
|
||||
default: push(tk);
|
||||
}
|
||||
if( tk != TPOpen ) unexpected(tk);
|
||||
ensure(TPOpen);
|
||||
var args = new Array();
|
||||
tk = token();
|
||||
if( tk != TPClose ) {
|
||||
while( true ) {
|
||||
var name = null;
|
||||
switch( tk ) {
|
||||
case TId(id): args.push(id);
|
||||
case TId(id): name = id;
|
||||
default: unexpected(tk);
|
||||
}
|
||||
tk = token();
|
||||
var t = null;
|
||||
if( tk == TDoubleDot && allowTypes ) {
|
||||
t = parseType();
|
||||
tk = token();
|
||||
}
|
||||
args.push({ name : name, t : t });
|
||||
switch( tk ) {
|
||||
case TComma:
|
||||
case TPClose: break;
|
||||
@@ -361,10 +383,18 @@ class Parser {
|
||||
tk = token();
|
||||
}
|
||||
}
|
||||
EFunction(args,parseExpr(),name);
|
||||
var ret = null;
|
||||
if( allowTypes ) {
|
||||
tk = token();
|
||||
if( tk != TDoubleDot )
|
||||
push(tk);
|
||||
else
|
||||
ret = parseType();
|
||||
}
|
||||
EFunction(args, parseExpr(), name, ret);
|
||||
case "return":
|
||||
var tk = token();
|
||||
tokens.add(tk);
|
||||
push(tk);
|
||||
EReturn(if( tk == TSemicolon ) null else parseExpr());
|
||||
case "new":
|
||||
var a = new Array();
|
||||
@@ -394,21 +424,23 @@ class Parser {
|
||||
case "try":
|
||||
var e = parseExpr();
|
||||
var tk = token();
|
||||
if( !Type.enumEq(tk,TId("catch")) ) unexpected(tk);
|
||||
tk = token();
|
||||
if( tk != TPOpen ) unexpected(tk);
|
||||
if( !Type.enumEq(tk, TId("catch")) ) unexpected(tk);
|
||||
ensure(TPOpen);
|
||||
tk = token();
|
||||
var vname = switch( tk ) {
|
||||
case TId(id): id;
|
||||
default: unexpected(tk);
|
||||
}
|
||||
tk = token();
|
||||
if( tk != TDoubleDot ) unexpected(tk);
|
||||
tk = token();
|
||||
if( !Type.enumEq(tk,TId("Dynamic")) ) unexpected(tk);
|
||||
tk = token();
|
||||
if( tk != TPClose ) unexpected(tk);
|
||||
ETry(e,vname,parseExpr());
|
||||
ensure(TDoubleDot);
|
||||
var t = null;
|
||||
if( allowTypes )
|
||||
t = parseType();
|
||||
else {
|
||||
tk = token();
|
||||
if( !Type.enumEq(tk, TId("Dynamic")) ) unexpected(tk);
|
||||
}
|
||||
ensure(TPClose);
|
||||
ETry(e,vname,t,parseExpr());
|
||||
default:
|
||||
null;
|
||||
}
|
||||
@@ -421,7 +453,7 @@ class Parser {
|
||||
for( x in unopsSuffix )
|
||||
if( x == op ) {
|
||||
if( isBlock(e1) || switch(e1) { case EParent(_): true; default: false; } ) {
|
||||
tokens.add(tk);
|
||||
push(tk);
|
||||
return e1;
|
||||
}
|
||||
return parseExprNext(EUnop(op,false,e1));
|
||||
@@ -439,21 +471,107 @@ class Parser {
|
||||
return parseExprNext(ECall(e1,parseExprList(TPClose)));
|
||||
case TBkOpen:
|
||||
var e2 = parseExpr();
|
||||
tk = token();
|
||||
if( tk != TBkClose ) unexpected(tk);
|
||||
ensure(TBkClose);
|
||||
return parseExprNext(EArray(e1,e2));
|
||||
case TQuestion:
|
||||
var e2 = parseExpr();
|
||||
tk = token();
|
||||
if( tk != TDoubleDot ) unexpected(tk);
|
||||
ensure(TDoubleDot);
|
||||
var e3 = parseExpr();
|
||||
return EIf(e1,e2,e3);
|
||||
default:
|
||||
tokens.add(tk);
|
||||
push(tk);
|
||||
return e1;
|
||||
}
|
||||
}
|
||||
|
||||
function parseType() : CType {
|
||||
var t = token();
|
||||
switch( t ) {
|
||||
case TId(v):
|
||||
var path = [v];
|
||||
while( true ) {
|
||||
t = token();
|
||||
if( t != TDot )
|
||||
break;
|
||||
t = token();
|
||||
switch( t ) {
|
||||
case TId(v):
|
||||
path.push(v);
|
||||
default:
|
||||
unexpected(t);
|
||||
}
|
||||
}
|
||||
var params = null;
|
||||
switch( t ) {
|
||||
case TOp(op):
|
||||
if( op == "<" ) {
|
||||
params = [];
|
||||
while( true ) {
|
||||
params.push(parseType());
|
||||
t = token();
|
||||
switch( t ) {
|
||||
case TComma: continue;
|
||||
case TOp(op): if( op == ">" ) break;
|
||||
default:
|
||||
}
|
||||
unexpected(t);
|
||||
}
|
||||
}
|
||||
default:
|
||||
push(t);
|
||||
}
|
||||
return parseTypeNext(CTPath(path, params));
|
||||
case TPOpen:
|
||||
var t = parseType();
|
||||
ensure(TPClose);
|
||||
return parseTypeNext(CTParent(t));
|
||||
case TBrOpen:
|
||||
var fields = [];
|
||||
while( true ) {
|
||||
t = token();
|
||||
switch( t ) {
|
||||
case TBrClose: break;
|
||||
case TId(name):
|
||||
ensure(TDoubleDot);
|
||||
fields.push( { name : name, t : parseType() } );
|
||||
t = token();
|
||||
switch( t ) {
|
||||
case TComma:
|
||||
case TBrClose: break;
|
||||
default: unexpected(t);
|
||||
}
|
||||
default:
|
||||
unexpected(t);
|
||||
}
|
||||
}
|
||||
return parseTypeNext(CTAnon(fields));
|
||||
default:
|
||||
return unexpected(t);
|
||||
}
|
||||
}
|
||||
|
||||
function parseTypeNext( t : CType ) {
|
||||
var tk = token();
|
||||
switch( tk ) {
|
||||
case TOp(op):
|
||||
if( op != "->" ) {
|
||||
push(tk);
|
||||
return t;
|
||||
}
|
||||
default:
|
||||
push(tk);
|
||||
return t;
|
||||
}
|
||||
var t2 = parseType();
|
||||
switch( t2 ) {
|
||||
case CTFun(args, ret):
|
||||
args.unshift(t);
|
||||
return t2;
|
||||
default:
|
||||
return CTFun([t], t2);
|
||||
}
|
||||
}
|
||||
|
||||
function parseExprList( etk ) {
|
||||
var args = new Array();
|
||||
var tk = token();
|
||||
|
||||
Reference in New Issue
Block a user