Skip to content

Commit

Permalink
added optional metadata support in toplevel expr and anon types
Browse files Browse the repository at this point in the history
  • Loading branch information
ncannasse committed Jul 18, 2017
1 parent a34faf8 commit 7ca5b85
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 49 deletions.
7 changes: 5 additions & 2 deletions hscript/Expr.hx
Original file line number Diff line number Diff line change
Expand Up @@ -70,14 +70,17 @@ enum Expr {
ETernary( cond : Expr, e1 : Expr, e2 : Expr );
ESwitch( e : Expr, cases : Array<{ values : Array<Expr>, expr : Expr }>, ?defaultExpr : Expr);
EDoWhile( cond : Expr, e : Expr);
EMeta( name : String, args : Array<Expr>, e : Expr );
}

typedef Argument = { name : String, ?t : CType, ?opt : Bool };

typedef Metadata = Array<{ name : String, params : Array<Expr> }>;

enum CType {
CTPath( path : Array<String>, ?params : Array<CType> );
CTFun( args : Array<CType>, ret : CType );
CTAnon( fields : Array<{ name : String, t : CType }> );
CTAnon( fields : Array<{ name : String, t : CType, ?meta : Metadata }> );
CTParent( t : CType );
}

Expand All @@ -99,7 +102,7 @@ class Error {
private function errorDefToString(): String {
switch (e) {
case EInvalidChar(c):
return "Invalid character: '"+c+"'";
return "Invalid character: '"+String.fromCharCode(c)+"' ("+c+")";

case EUnexpected(s):
return "Unexpected token: \""+s+"\"";
Expand Down
8 changes: 5 additions & 3 deletions hscript/Interp.hx
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ class Interp {
else {
arr[index] = v;
}

default:
error(EInvalidOp("="));
}
Expand Down Expand Up @@ -560,6 +560,8 @@ class Interp {
if( !match )
val = def == null ? null : expr(def);
return val;
case EMeta(_, _, e):
return expr(e);
}
return null;
}
Expand Down Expand Up @@ -629,15 +631,15 @@ class Interp {
inline function isMap(o:Dynamic):Bool {
return Std.is(o, haxe.Constraints.IMap);
}

inline function getMapValue(map:Dynamic, key:Dynamic):Dynamic {
return cast(map, haxe.Constraints.IMap<Dynamic, Dynamic>).get(key);
}

inline function setMapValue(map:Dynamic, key:Dynamic, value:Dynamic):Void {
cast(map, haxe.Constraints.IMap<Dynamic, Dynamic>).set(key, value);
}

function get( o : Dynamic, f : String ) : Dynamic {
if ( o == null ) error(EInvalidAccess(f));
return {
Expand Down
3 changes: 3 additions & 0 deletions hscript/Macro.hx
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,9 @@ class Macro {
ETernary(convert(cond), convert(e1), convert(e2));
case ESwitch(e, cases, edef):
ESwitch(convert(e), [for( c in cases ) { values : [for( v in c.values ) convert(v)], expr : convert(c.expr) } ], edef == null ? null : convert(edef));
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));
}, pos : #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end }
}

Expand Down
123 changes: 79 additions & 44 deletions hscript/Parser.hx
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ enum Token {
TBkClose;
TQuestion;
TDoubleDot;
TMeta( s : String );
}

class Parser {
Expand Down Expand Up @@ -69,6 +70,11 @@ class Parser {
**/
public var allowTypes : Bool;

/**
allow haxe metadata declarations
**/
public var allowMetadata : Bool;

// implementation
var input : haxe.io.Input;
var char : Int;
Expand Down Expand Up @@ -200,6 +206,16 @@ class Parser {
if( t != tk ) unexpected(t);
}

function getIdent() {
var tk = token();
switch( tk ) {
case TId(id): return id;
default:
unexpected(tk);
return null;
}
}

inline function expr(e:Expr) {
#if hscriptPos
return e.e;
Expand Down Expand Up @@ -384,12 +400,39 @@ class Parser {
return parseExprNext(e);
default:
}
return parseExprNext(mk(EArrayDecl(a),p1));
return parseExprNext(mk(EArrayDecl(a), p1));
case TMeta(id) if( allowMetadata ):
var args = parseMetaArgs();
return mk(EMeta(id, args, parseExpr()),p1);
default:
return unexpected(tk);
}
}

function parseMetaArgs() {
var tk = token();
if( tk != TPOpen ) {
push(tk);
return null;
}
var args = [];
tk = token();
if( tk != TPClose ) {
push(tk);
while( true ) {
args.push(parseExpr());
switch( token() ) {
case TComma:
case TPClose:
break;
case tk:
unexpected(tk);
}
}
}
return args;
}

function mapCompr( tmp : String, e : Expr ) {
var edef = switch( expr(e) ) {
case EFor(v, it, e2):
Expand Down Expand Up @@ -460,13 +503,8 @@ class Parser {
}
mk(EIf(cond,e1,e2),p1,(e2 == null) ? tokenMax : pmax(e2));
case "var":
var ident = getIdent();
var tk = token();
var ident = null;
switch(tk) {
case TId(id): ident = id;
default: unexpected(tk);
}
tk = token();
var t = null;
if( tk == TDoubleDot && allowTypes ) {
t = parseType();
Expand Down Expand Up @@ -494,13 +532,8 @@ class Parser {
mk(EDoWhile(econd,e),p1,pmax(econd));
case "for":
ensure(TPOpen);
var vname = getIdent();
var tk = token();
var vname = null;
switch( tk ) {
case TId(id): vname = id;
default: unexpected(tk);
}
tk = token();
if( !Type.enumEq(tk,TId("in")) ) unexpected(tk);
var eiter = parseExpr();
ensure(TPClose);
Expand Down Expand Up @@ -568,21 +601,13 @@ class Parser {
mk(EReturn(e),p1,if( e == null ) tokenMax else pmax(e));
case "new":
var a = new Array();
var tk = token();
switch( tk ) {
case TId(id): a.push(id);
default: unexpected(tk);
}
a.push(getIdent());
var next = true;
while( next ) {
tk = token();
var tk = token();
switch( tk ) {
case TDot:
tk = token();
switch(tk) {
case TId(id): a.push(id);
default: unexpected(tk);
}
a.push(getIdent());
case TPOpen:
next = false;
default:
Expand All @@ -599,11 +624,7 @@ class Parser {
var tk = token();
if( !Type.enumEq(tk, TId("catch")) ) unexpected(tk);
ensure(TPOpen);
tk = token();
var vname = switch( tk ) {
case TId(id): id;
default: unexpected(tk);
}
var vname = getIdent();
ensure(TDoubleDot);
var t = null;
if( allowTypes )
Expand Down Expand Up @@ -700,12 +721,7 @@ class Parser {
}
return makeBinop(op,e1,parseExpr());
case TDot:
tk = token();
var field = null;
switch(tk) {
case TId(id): field = id;
default: unexpected(tk);
}
var field = getIdent();
return parseExprNext(mk(EField(e1,field),pmin(e1)));
case TPOpen:
return parseExprNext(mk(ECall(e1,parseExprList(TPClose)),pmin(e1)));
Expand Down Expand Up @@ -733,13 +749,7 @@ class Parser {
t = token();
if( t != TDot )
break;
t = token();
switch( t ) {
case TId(v):
path.push(v);
default:
unexpected(t);
}
path.push(getIdent());
}
var params = null;
switch( t ) {
Expand All @@ -758,7 +768,7 @@ class Parser {
tokens.add({ t : TOp(op.substr(1)), min : tokenMax - op.length - 1, max : tokenMax });
#else
tokens.add(TOp(op.substr(1)));
#end
#end
break;
}
default:
Expand All @@ -777,19 +787,29 @@ class Parser {
return parseTypeNext(CTParent(t));
case TBrOpen:
var fields = [];
var meta = null;
while( true ) {
t = token();
switch( t ) {
case TBrClose: break;
case TId("var"):
var name = getIdent();
ensure(TDoubleDot);
fields.push( { name : name, t : parseType(), meta : meta } );
meta = null;
ensure(TSemicolon);
case TId(name):
ensure(TDoubleDot);
fields.push( { name : name, t : parseType() } );
fields.push( { name : name, t : parseType(), meta : meta } );
t = token();
switch( t ) {
case TComma:
case TBrClose: break;
default: unexpected(t);
}
case TMeta(name):
if( meta == null ) meta = [];
meta.push({ name : name, params : parseMetaArgs() });
default:
unexpected(t);
}
Expand Down Expand Up @@ -1082,6 +1102,20 @@ class Parser {
return TOp("=>");
this.char = char;
return TOp("=");
case '@'.code:
char = readChar();
if( idents[char] || char == ':'.code ) {
var id = String.fromCharCode(char);
while( true ) {
char = readChar();
if( !idents[char] ) {
this.char = char;
return TMeta(id);
}
id += String.fromCharCode(char);
}
}
invalidChar(char);
default:
if( ops[char] ) {
var op = String.fromCharCode(char);
Expand Down Expand Up @@ -1186,6 +1220,7 @@ class Parser {
case TBkClose: "]";
case TQuestion: "?";
case TDoubleDot: ":";
case TMeta(id): "@" + id;
}
}

Expand Down

0 comments on commit 7ca5b85

Please sign in to comment.