Compare commits

..
1 Commits
Author SHA1 Message Date
Nicolas Cannasse 8b9b244512 fix overflow on bigint platforms (close #42) 2017-05-06 11:17:58 +02:00
17 changed files with 332 additions and 1429 deletions
+11 -9
View File
@@ -4,12 +4,10 @@ os:
- linux
- osx
sudo: false
dist: trusty
osx_image: xcode6.4
haxe:
- "3.2.1"
- "3.4.2"
- development
addons:
@@ -20,25 +18,30 @@ addons:
- g++-multilib
# Python
- python3
# PHP
- php5-cli
# C#
- mono-devel
- mono-mcs
# Flash
- libglib2.0
- libfreetype6
- libcurl3:i386
- libglib2.0-0:i386
- libx11-6:i386
- libxext6:i386
- libxt6:i386
- libxcursor1:i386
- libnss3:i386
- libgtk2.0-0:i386
install:
# os-specific config
- if [ "${TRAVIS_OS_NAME}" = "linux" ]; then
export DISPLAY=:99.0;
export AUDIODEV=null;
phpenv global 7.0;
elif [ "${TRAVIS_OS_NAME}" = "osx" ]; then
brew update;
brew install mono;
brew install python3;
brew tap homebrew/homebrew-php;
brew install php71;
fi
# Download and setup a standalone flash player debugger
- haxe flash/install.hxml
@@ -54,7 +57,6 @@ install:
fi
- haxelib install hxjava
- haxelib install hxcs
- haxelib install hx3compat
- haxelib dev hscript .
- haxelib list
-22
View File
@@ -1,22 +0,0 @@
The MIT License
Copyright (C)2008-2017 Haxe Foundation
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-2
View File
@@ -64,8 +64,6 @@ You can use `parser.allowJSON` to allow JSON data.
You can use `parser.allowTypes` to parse types for local vars, exceptions, function args and return types. Types are ignored by the interpreter.
You can use `parser.allowMetadata` to parse metadata before expressions on in anonymous types. Metadata are ignored by the interpreter.
You can use `new hscript.Macro(pos).convert(ast)` to convert an hscript AST to a Haxe macros one.
Limitations
-10
View File
@@ -1,9 +1,6 @@
import haxe.ds.EnumValueMap;
import haxe.ds.Option;
import hscript.Macro;
import hscript.Tools;
import hscript.Async;
import hscript.Printer;
import haxe.unit.*;
class Test extends TestCase {
@@ -24,15 +21,8 @@ class Test extends TestCase {
function test():Void {
assertScript("0",0);
assertScript("0xFF", 255);
#if !(php || python)
#if haxe3
assertScript("0xBFFFFFFF", 0xBFFFFFFF);
assertScript("0x7FFFFFFF", 0x7FFFFFFF);
#elseif !neko
assertScript("n(0xBFFFFFFF)", 0xBFFFFFFF, { n : haxe.Int32.toNativeInt });
assertScript("n(0x7FFFFFFF)", 0x7FFFFFFF, { n : haxe.Int32.toNativeInt } );
#end
#end
assertScript("-123",-123);
assertScript("- 123",-123);
assertScript("1.546",1.546);
+2 -5
View File
@@ -6,22 +6,19 @@ environment:
install:
# Install the haxe chocolatey package (https://chocolatey.org/packages/haxe)
- cinst haxe -version 3.4.2 -y
- cinst haxe -version 3.2.1 -y
- RefreshEnv
# Setup haxelib
- mkdir "%HAXELIB_ROOT%"
- haxelib setup "%HAXELIB_ROOT%"
# Install test dependencies
- ps: Set-Service wuauserv -StartupType Manual
- cinst php -y
- RefreshEnv
# Download and setup a standalone flash player debugger
- haxe flash/install.hxml
# Install project dependencies
- haxelib install hxcpp > log.txt || type log.txt && cmd /C exit 1
- haxelib install hxjava > log.txt || type log.txt && cmd /C exit 1
- haxelib install hxcs > log.txt || type log.txt && cmd /C exit 1
- haxelib install hx3compat > log.txt || type log.txt && cmd /C exit 1
- haxelib dev hscript .
- haxelib list
@@ -38,5 +35,5 @@ test_script:
- haxe bin/build-cs.hxml && bin\bin\Test.exe
- haxe bin/build-cpp.hxml && bin\Test.exe
- haxe bin/build-flash.hxml -D fdb && haxe flash\run.hxml bin\Test.swf
- haxe bin/build-php.hxml && php bin\index.php
- haxe bin/build-php.hxml && C:\tools\php\php.exe bin\index.php
- haxe bin/build-python.hxml && C:\Python34-x64\python.exe bin\Test.py
-1
View File
@@ -1,3 +1,2 @@
-main Test
-dce no
-lib hx3compat
+4 -7
View File
@@ -7,11 +7,11 @@ class Install {
// https://www.adobe.com/support/flashplayer/downloads.html
static var fpDownload(default, never) = switch (systemName()) {
case "Linux":
"http://fpdownload.macromedia.com/pub/flashplayer/updaters/25/flash_player_sa_linux_debug.x86_64.tar.gz";
"https://fpdownload.macromedia.com/pub/flashplayer/updaters/11/flashplayer_11_sa_debug.i386.tar.gz";
case "Mac":
"http://fpdownload.macromedia.com/pub/flashplayer/updaters/25/flashplayer_25_sa_debug.dmg";
"https://fpdownload.macromedia.com/pub/flashplayer/updaters/21/flashplayer_21_sa_debug.dmg";
case "Windows":
"http://fpdownload.macromedia.com/pub/flashplayer/updaters/25/flashplayer_25_sa_debug.exe";
"http://fpdownload.macromedia.com/pub/flashplayer/updaters/21/flashplayer_21_sa_debug.exe";
case _:
throw "unsupported system";
}
@@ -46,9 +46,6 @@ class Install {
if (command("tar", ["-xf", Path.withoutDirectory(fpDownload), "-C", "flash"]) != 0)
throw "failed to extract flash player";
case "Mac":
// https://github.com/caskroom/homebrew-cask/pull/15381
if (command("brew", ["uninstall", "--force", "brew-cask"]) != 0)
throw "failed to brew uninstall --force brew-cask";
if (command("brew", ["tap", "caskroom/versions"]) != 0)
throw "failed to brew tap caskroom/versions";
if (command("brew", ["cask", "install", "flash-player-debugger"]) != 0)
@@ -87,7 +84,7 @@ class Install {
if (command("sudo", ["chmod", "a+rw", dir]) != 0)
throw 'cannot set permission of $dir';
case _:
throw 'cannot create $dir: $e';
neko.Lib.rethrow(e);
}
}
}
+3 -4
View File
@@ -21,13 +21,12 @@ class Run {
var exitCode = switch (systemName()) {
case "Linux":
// The flash player has some issues with unexplained crashes,
// but if it runs about 16 times, it should succeed one of those...
// but if it runs about 8 times, it should succeed one of those...
var c = -1;
for (i in 0...16) {
if ((c = command("xvfb-run", ["-a", "flash/flashplayerdebugger", swf])) == 0)
for (i in 0...8) {
if ((c = command("xvfb-run", ["flash/flashplayerdebugger", swf])) == 0)
break;
println('retry... (${i+1})');
sleep(1.5);
}
c;
case "Mac":
+2 -2
View File
@@ -3,7 +3,7 @@
"url": "https://github.com/HaxeFoundation/hscript",
"license": "MIT",
"description": "Haxe Script is a scripting engine for a subset of the Haxe language",
"version": "2.2.0",
"releasenote": "",
"version": "2.0.7",
"releasenote": "fixes for haxe 3.3, use property access by default",
"contributors": ["ncannasse"]
}
-494
View File
@@ -1,494 +0,0 @@
/*
* Copyright (C)2008-2017 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
import hscript.Expr;
class Async {
var varNames : Array<String>;
var currentFun : String;
var currentLoop : Expr;
var currentBreak : Expr -> Expr;
var uid = 0;
static var nullExpr : Expr = #if hscriptPos { e : null, pmin : 0, pmax : 0, origin : "<null>", line : 0 } #else null #end;
static var nullId = mk(EIdent("null"), nullExpr);
inline static function expr( e : Expr ) {
return #if hscriptPos e.e #else e #end;
}
inline static function mk( e, inf : Expr ) : Expr {
return #if hscriptPos { e : e, pmin : inf.pmin, pmax : inf.pmax, origin : inf.origin, line : inf.line } #else e #end;
}
/**
Convert a script into asynchronous one.
- calls such as foo(a,b,c) are translated to a_foo(function(r) ...rest, a,b,c) where r is the result value
- object access such obj.bar(a,b,c) are translated to obj.a_bar(function(r) ...rest, a, b, c)
- @async expr will execute the expression but continue without waiting for it to finish
- @split [ e1, e2, e3 ] is transformed to split(function(_) ...rest, [e1, e2, e3]) which
should execute asynchronously all expressions - until they return - before continuing the execution
- for(i in v) block; loops are translated to the following:
var _i = makeIterator(v);
function _loop() {
if( !_i.hasNext() ) return;
var v = _i.next();
block(function(_) _loop());
}
_loop()
- while loops are translated similar to for loops
- break and continue are correctly handled
- you can use @sync <expr> to disable async transformation in some code parts (for performance reason)
- a few expressions are still not supported (complex calls, try/catch, and a few others)
In these examples ...rest represents the continuation of execution of the script after the expression
**/
public static function toAsync( e : Expr, topLevelSync = false ) {
var a = new Async();
return a.build(e, topLevelSync);
}
public function build( e : Expr, topLevelSync = false ) {
if( topLevelSync ) {
return buildSync(e,null);
} else {
var nothing = ignore();
return new Async().toCps(e, nothing, nothing);
}
}
function buildSync( e : Expr, exit : Expr ) : Expr {
switch( expr(e) ) {
case EFunction(_):
return toCps(e, null, null);
case EBlock(el):
var v = saveVars();
for( e in el )
switch( expr(e) ) {
case EFunction(_, _, name, _) if( name != null ): varNames.push(name);
default:
}
var e = block([for(e in el) buildSync(e,exit)], e);
restoreVars(v);
return e;
case EMeta("async", _, e):
return toCps(e, ignore(), ignore());
case EBreak if( currentBreak != null ):
return currentBreak(e);
case EContinue if( currentLoop != null ):
return block([call(currentLoop, [nullId], e), mk(EReturn(),e)],e);
case EFor(_), EWhile(_):
var oldLoop = currentLoop, oldBreak = currentBreak;
currentLoop = null;
currentBreak = null;
e = Tools.map(e, buildSync.bind(_, exit));
currentLoop = oldLoop;
currentBreak = oldBreak;
return e;
case EReturn(eret) if( exit != null ):
return block([call(exit,[eret == null ? nullId : eret], e), mk(EReturn(),e)], e);
default:
return Tools.map(e, buildSync.bind(_, exit));
}
}
public function new() {
varNames = [];
}
function ignore(?e) : Expr {
var inf = e == null ? nullExpr : e;
return fun("_", block(e == null ? [] : [e],inf));
}
inline function ident(str, e) {
return mk(EIdent(str), e);
}
inline function fun(arg:String, e, ?name) {
return mk(EFunction([{ name : arg, t : null }], e, name), e);
}
inline function funs(arg:Array<String>, e, ?name) {
return mk(EFunction([for( a in arg ) { name : a, t : null }], e, name), e);
}
inline function block(arr, e) {
return mk(EBlock(arr), e);
}
inline function field(e, f, inf) {
return mk(EField(e, f), inf);
}
inline function binop(op, e1, e2, inf) {
return mk(EBinop(op, e1, e2), inf);
}
inline function call(e, args, inf) {
return mk(ECall(e, args), inf);
}
function retNull(e) : Expr {
return call(e, [nullId],e);
}
function makeCall( ecall, args : Array<Expr>, rest : Expr, exit, sync = false ) {
var names = [for( i in 0...args.length ) "_a"+uid++];
var rargs = [for( i in 0...args.length ) ident(names[i],ecall)];
if( !sync )
rargs.unshift(rest);
var rest = mk(sync ? ECall(rest,[call(ecall, rargs,ecall)]) : ECall(ecall, rargs), ecall);
var i = args.length - 1;
while( i >= 0 ) {
rest = toCps(args[i], fun(names[i], rest), exit);
i--;
}
return rest;
}
var syncFlag : Bool;
function isSync( e : Expr ) {
syncFlag = true;
checkSync(e);
return syncFlag;
}
function checkSync( e : Expr ) {
if( !syncFlag )
return;
switch( expr(e) ) {
case ECall(_), EFunction(_):
syncFlag = false;
case EMeta("sync" | "async", _, _):
// isolated from the sync part
default:
Tools.iter(e, checkSync);
}
}
function saveVars() {
return varNames.length;
}
function restoreVars(k) {
while( varNames.length > k ) varNames.pop();
}
public function toCps( e : Expr, rest : Expr, exit : Expr ) : Expr {
if( isSync(e) )
return call(rest, [buildSync(e, exit)],e);
switch( expr(e) ) {
case EBlock(el):
var el = el.copy();
var vold = saveVars();
// local recursion
for( e in el )
switch( expr(e) ) {
case EFunction(_, _, name, null): varNames.push(name);
default:
}
while( el.length > 0 ) {
var e = toCps(el.pop(), rest, exit);
rest = ignore(e);
}
restoreVars(vold);
return retNull(rest);
case EFunction(args, body, name, t):
var vold = saveVars();
if( name != null )
varNames.push(name);
for( a in args )
varNames.push(a.name);
args.unshift( { name : "_onEnd", t : null } );
var frest = ident("_onEnd",e);
var oldFun = currentFun;
currentFun = name;
var body = toCps(body, frest, frest);
var f = mk(EFunction(args, body, name, t),e);
restoreVars(vold);
return rest == null ? f : call(rest, [f],e);
case EParent(e):
return mk(EParent(toCps(e, rest, exit)),e);
case EMeta("sync", _, e):
return call(rest,[buildSync(e,exit)],e);
case EMeta("async", _, e):
var nothing = ignore();
return block([toCps(e,nothing,nothing),retNull(rest)],e);
case EMeta("split", _, e):
var args = switch( expr(e) ) { case EArrayDecl(el): el; default: throw "@split expression should be an array"; };
var args = [for( a in args ) fun("_rest", toCps(block([a],a), ident("_rest",a), exit))];
return call(ident("split",e), [rest, mk(EArrayDecl(args),e)],e);
case ECall(expr(_) => EIdent(i), args):
return makeCall( ident( varNames.indexOf(i) < 0 ? "a_" + i : i,e) , args, rest, exit);
case ECall(expr(_) => EField(e, f), args):
return makeCall(field(e,"a_"+f,e), args, rest, exit);
case EFor(v, eit, eloop):
var id = ++uid;
var it = ident("_i" + id,e);
var oldLoop = currentLoop, oldBreak = currentBreak;
var loop = ident("_loop" + id,e);
currentLoop = loop;
currentBreak = function(inf) return block([call(rest, [nullId], inf), mk(EReturn(),inf)], inf);
var efor = block([
mk(EVar("_i" + id, call(ident("makeIterator",eit),[eit],eit)),eit),
fun("_", block([
mk(EIf(mk(EUnop("!", true, call( field(it, "hasNext", it), [], it)),it), currentBreak(it)),it),
mk(EVar(v, call(field(it, "next",it), [], it)), it),
toCps(eloop, loop, exit),
], it),"_loop" + id),
call(loop, [nullId], e),
], e);
currentLoop = oldLoop;
currentBreak = oldBreak;
return efor;
case EUnop(op = "!", prefix, eop):
return toCps(eop, fun("_r",call(rest, [mk(EUnop(op, prefix, ident("_r",e)),e)], e)), exit);
case EBinop(op, e1, e2):
switch( op ) {
case "=", "+=", "-=", "/=", "*=", "%=", "&=", "|=", "^=":
switch( expr(e1) ) {
case EIdent(_):
var id = "_r" + uid++;
return toCps(e2, fun(id, call(rest, [binop(op, e1, ident(id,e1),e1)], e1)), exit);
case EField(ef1, f):
var id1 = "_r" + uid++;
var id2 = "_r" + uid++;
return toCps(ef1, fun(id1, toCps(e2, fun(id2, call(rest, [binop(op, field(ident(id1, e1), f, ef1), ident(id2, e2), e)], e)), exit)), exit);
case EArray(earr, eindex):
var idArr = "_r" + uid++;
var idIndex = "_r" + uid++;
var idVal = "_r" + uid++;
return toCps(earr,fun(idArr, toCps(eindex, fun(idIndex, toCps(e2,
fun(idVal, call(rest, [binop(op, mk(EArray(ident(idArr,earr), ident(idIndex,eindex)),e1), ident(idVal,e1), e)], e))
, exit)), exit)),exit);
default:
throw "assert " + e1;
}
case "||":
var id1 = "_r" + uid++;
var id2 = "_r" + uid++;
return toCps(e1, fun(id1, mk(EIf(binop("==", ident(id1,e1), ident("true",e1), e1),call(rest,[ident("true",e1)],e1),toCps(e2, rest, exit)),e)), exit);
case "&&":
var id1 = "_r" + uid++;
var id2 = "_r" + uid++;
return toCps(e1, fun(id1, mk(EIf(binop("!=", ident(id1,e1), ident("true",e1), e1),call(rest,[ident("false",e1)],e1),toCps(e2, rest, exit)),e)), exit);
default:
var id1 = "_r" + uid++;
var id2 = "_r" + uid++;
return toCps(e1, fun(id1, toCps(e2, fun(id2, call(rest, [binop(op, ident(id1,e1), ident(id2,e2), e)], e)), exit)), exit);
}
case EIf(cond, e1, e2), ETernary(cond, e1, e2):
return toCps(cond, fun("_c", mk(EIf(ident("_c",cond), toCps(e1, rest, exit), e2 == null ? retNull(rest) : toCps(e2, rest, exit)),e)), exit);
case EWhile(cond, ewh):
var id = ++uid;
var loop = ident("_loop" + id, cond);
var oldLoop = currentLoop, oldBreak = currentBreak;
currentLoop = loop;
currentBreak = function(e) return block([call(rest, [nullId], e), mk(EReturn(),e)],e);
var ewhile = block([
fun("_r",
toCps(cond, fun("_c", mk(EIf(ident("_c", cond), toCps(ewh, loop, exit), call(rest, [nullId], cond)),cond)), exit)
, "_loop"+id),
call(loop, [nullId], cond),
],e);
currentLoop = oldLoop;
currentBreak = oldBreak;
return ewhile;
case EReturn(eret):
return eret == null ? call(exit, [nullId], e) : toCps(eret, exit, exit);
case EObject(fields):
var id = "_o" + uid++;
var rest = call(rest, [ident(id,e)], e);
fields.reverse();
for( f in fields )
rest = toCps(f.e, fun("_r", block([
binop("=", mk(EField(ident(id,f.e), f.name),f.e), ident("_r",f.e), f.e),
rest,
],f.e)),exit);
return block([
mk(EVar(id, mk(EObject([]),e)),e),
rest,
],e);
case EArrayDecl(el):
var id = "_a" + uid++;
var rest = call(rest, [ident(id,e)], e);
var i = el.length - 1;
while( i >= 0 ) {
var e = el[i];
rest = toCps(e, fun("_r", block([
binop("=", mk(EArray(ident(id,e), mk(EConst(CInt(i)),e)),e), ident("_r",e), e),
rest,
],e)), exit);
i--;
}
return block([
mk(EVar(id, mk(EArrayDecl([]),e)),e),
rest,
],e);
case EArray(earr, eindex):
var id1 = "_r" + uid++;
var id2 = "_r" + uid++;
return toCps(earr, fun(id1, toCps(eindex, fun(id2, call(rest, [mk(EArray(ident(id1,e), ident(id2,e)),e)], e)), exit)), exit);
case EVar(v, t, ev):
if( ev == null )
return block([e, call(rest, [nullId],e)], e);
return block([
mk(EVar(v, t),e),
toCps(ev, fun("_r", block([binop("=", ident(v,e), ident("_r",e), e), call(rest,[nullId],e)], e)), exit),
],e);
case EConst(_), EIdent(_), EUnop(_), EField(_):
return call(rest, [e], e);
case ENew(cl, args):
var names = [for( i in 0...args.length ) "_a"+uid++];
var rargs = [for( i in 0...args.length ) ident(names[i], args[i])];
var rest = call(rest,[mk(ENew(cl, rargs),e)],e);
var i = args.length - 1;
while( i >= 0 ) {
rest = toCps(args[i], fun(names[i], rest), exit);
i--;
}
return rest;
case EBreak:
if( currentBreak == null ) throw "Break outside loop";
return currentBreak(e);
case EContinue:
if( currentLoop == null ) throw "Continue outside loop";
return block([call(currentLoop, [nullId], e), mk(EReturn(),e)], e);
case ESwitch(v, cases, def):
var cases = [for( c in cases ) { values : c.values, expr : toCps(c.expr, rest, exit) } ];
return toCps(v, mk(EFunction([ { name : "_c", t : null } ], mk(ESwitch(ident("_c",v), cases, def == null ? retNull(rest) : toCps(def, rest, exit)),e)),e), exit );
case EThrow(v):
return toCps(v, mk(EFunction([ { name : "_v", t : null } ], mk(EThrow(v),v)), v), exit);
//case EDoWhile(_), ETry(_), ECall(_):
default:
throw "Unsupported async expression " + Printer.toString(e);
}
}
}
class AsyncInterp extends Interp {
public function setContext( api : Dynamic ) {
var funs = new Array();
for( v in variables.keys() )
if( Reflect.isFunction(variables.get(v)) )
funs.push({ v : v, obj : null });
variables.set("split", split);
variables.set("makeIterator", makeIterator);
var c = Type.getClass(api);
for( f in (c == null ? Reflect.fields(api) : Type.getInstanceFields(c)) ) {
var fv = Reflect.field(api, f);
if( !Reflect.isFunction(fv) ) continue;
if( f.charCodeAt(0) == "_".code ) f = f.substr(1);
variables.set(f, fv);
// create the async wrapper if doesn't exists
if( f.substr(0, 2) != "a_" )
funs.push({ v : f, obj : api });
}
for( v in funs ) {
if( variables.exists("a_" + v.v) ) continue;
var fv : Dynamic = variables.get(v.v);
var obj = v.obj;
variables.set("a_" + v.v, Reflect.makeVarArgs(function(args:Array<Dynamic>) {
var onEnd = args.shift();
onEnd(Reflect.callMethod(obj, fv, args));
}));
}
}
public function hasMethod( name : String ) {
var v = variables.get(name);
return v != null && Reflect.isFunction(v);
}
public function callValue( value : Dynamic, args : Array<Dynamic>, ?onResult : Dynamic -> Void, ?vthis : {} ) {
var oldThis = variables.get("this");
if( vthis != null )
variables.set("this", vthis);
if( onResult == null )
onResult = function(_) {};
args.unshift(onResult);
Reflect.callMethod(null, value, args);
variables.set("this", oldThis);
}
public function callAsync( id : String, args, ?onResult, ?vthis : {} ) {
var v = variables.get(id);
if( v == null )
throw "Missing function " + id + "()";
callValue(v, args, onResult, vthis);
}
function split( rest : Dynamic -> Void, args : Array<Dynamic> ) {
if( args.length == 0 )
rest(null);
else {
var count = args.length;
function next(_) {
if( --count == 0 ) rest(null);
}
for( a in args )
a(next);
}
}
override function fcall( o : Dynamic, f : String, args : Array<Dynamic> ) : Dynamic {
var m = Reflect.field(o, f);
if( m == null ) {
if( f.substr(0, 2) == "a_" ) {
m = Reflect.field(o, f.substr(2));
// fallback on sync version
if( m != null ) {
var onEnd = args.shift();
onEnd(call(o, m, args));
return null;
}
// fallback on generic script
m = Reflect.field(o, "scriptCall");
if( m != null ) {
call(o, m, [args.shift(), f.substr(2), args]);
return null;
}
} else {
// fallback on generic script
m = Reflect.field(o, "scriptCall");
if( m != null ) {
var result : Dynamic = null;
call(o, m, [function(r) result = r, f, args]);
return result;
}
}
error(ECustom(o + " has no method " + f));
}
return call(o, m, args);
}
}
+20 -27
View File
@@ -1,23 +1,26 @@
/*
* Copyright (C)2008-2017 Haxe Foundation
* Copyright (c) 2008, Nicolas Cannasse
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package hscript;
import hscript.Expr;
@@ -244,11 +247,6 @@ class Bytes {
}
bout.addByte(255);
if( def == null ) bout.addByte(255) else doEncode(def);
case EMeta(name,args,e):
doEncodeString(name);
bout.addByte(args == null ? 0 : args.length + 1);
if( args != null ) for( e in args ) doEncode(e);
doEncode(e);
}
}
@@ -368,11 +366,6 @@ class Bytes {
case 24:
var cond = doDecode();
EDoWhile(cond,doDecode());
case 25:
var name = doDecodeString();
var count = bin.get(pin++);
var args = count == 0 ? null : [for( i in 0...count - 1 ) doDecode()];
EMeta(name, args, doDecode());
case 255:
null;
default:
+54 -85
View File
@@ -1,23 +1,26 @@
/*
* Copyright (C)2008-2017 Haxe Foundation
* Copyright (c) 2008, Nicolas Cannasse
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package hscript;
@@ -67,17 +70,14 @@ 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, ?value : Expr };
typedef Metadata = Array<{ name : String, params : Array<Expr> }>;
typedef Argument = { name : String, ?t : CType, ?opt : Bool };
enum CType {
CTPath( path : Array<String>, ?params : Array<CType> );
CTFun( args : Array<CType>, ret : CType );
CTAnon( fields : Array<{ name : String, t : CType, ?meta : Metadata }> );
CTAnon( fields : Array<{ name : String, t : CType }> );
CTParent( t : CType );
}
@@ -95,8 +95,39 @@ class Error {
this.origin = origin;
this.line = line;
}
private function errorDefToString(): String {
switch (e) {
case EInvalidChar(c):
return "Invalid character: '"+c+"'";
case EUnexpected(s):
return "Unexpected token: \""+s+"\"";
case EUnterminatedString:
return "Unterminated string";
case EUnterminatedComment:
return "Unterminated comment";
case EUnknownVariable(v):
return "Unknown variable: "+v;
case EInvalidIterator(v):
return "Invalid iterator: "+v;
case EInvalidOp(op):
return "Invalid operator: "+op;
case EInvalidAccess(f):
return "Invalid access to field "+f;
}
}
public function toString(): String {
return Printer.errorToString(this);
var message = errorDefToString();
message = origin + ":" + line + ": " + message;
return message;
}
}
enum ErrorDef {
@@ -107,70 +138,8 @@ enum Error {
EUnexpected( s : String );
EUnterminatedString;
EUnterminatedComment;
EInvalidPreprocessor( msg : String );
EUnknownVariable( v : String );
EInvalidIterator( v : String );
EInvalidOp( op : String );
EInvalidAccess( f : String );
ECustom( msg : String );
}
enum ModuleDecl {
DPackage( path : Array<String> );
DImport( path : Array<String>, ?everything : Bool );
DClass( c : ClassDecl );
DTypedef( c : TypeDecl );
}
typedef ModuleType = {
var name : String;
var params : {}; // TODO : not yet parsed
var meta : Metadata;
var isPrivate : Bool;
}
typedef ClassDecl = {> ModuleType,
var extend : Null<CType>;
var implement : Array<CType>;
var fields : Array<FieldDecl>;
var isExtern : Bool;
}
typedef TypeDecl = {> ModuleType,
var t : CType;
}
typedef FieldDecl = {
var name : String;
var meta : Metadata;
var kind : FieldKind;
var access : Array<FieldAccess>;
}
enum FieldAccess {
APublic;
APrivate;
AInline;
AOverride;
AStatic;
AMacro;
}
enum FieldKind {
KFunction( f : FunctionDecl );
KVar( v : VarDecl );
}
typedef FunctionDecl = {
var args : Array<Argument>;
var expr : Expr;
var ret : Null<CType>;
}
typedef VarDecl = {
var get : Null<String>;
var set : Null<String>;
var expr : Null<Expr>;
var type : Null<CType>;
}
+32 -46
View File
@@ -1,23 +1,26 @@
/*
* Copyright (C)2008-2017 Haxe Foundation
* Copyright (c) 2008, Nicolas Cannasse
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package hscript;
import haxe.PosInfos;
@@ -26,7 +29,7 @@ import hscript.Expr;
private enum Stop {
SBreak;
SContinue;
SReturn;
SReturn( v : Dynamic );
}
class Interp {
@@ -44,7 +47,6 @@ class Interp {
var depth : Int;
var inTry : Bool;
var declared : Array<{ n : String, old : { r : Dynamic } }>;
var returnValue : Dynamic;
#if hscriptPos
var curExpr : Expr;
@@ -62,12 +64,7 @@ class Interp {
variables.set("null",null);
variables.set("true",true);
variables.set("false",false);
variables.set("trace", Reflect.makeVarArgs(function(el) {
var inf = posInfos();
var v = el.shift();
if( el.length > 0 ) inf.customParams = el;
haxe.Log.trace(Std.string(v), inf);
}));
variables.set("trace",function(e) haxe.Log.trace(Std.string(e), posInfos()));
initOps();
}
@@ -253,10 +250,7 @@ class Interp {
switch( e ) {
case SBreak: throw "Invalid break";
case SContinue: throw "Invalid continue";
case SReturn:
var v = returnValue;
returnValue = null;
return v;
case SReturn(v): return v;
}
}
return null;
@@ -288,18 +282,13 @@ class Interp {
#end
}
inline function error(e : #if hscriptPos ErrorDef #else Error #end, rethrow=false ) : Dynamic {
#if hscriptPos var e = new Error(e, curExpr.pmin, curExpr.pmax, curExpr.origin, curExpr.line); #end
if( rethrow ) this.rethrow(e) else throw e;
return null;
}
inline function rethrow( e : Dynamic ) {
#if hl
hl.Api.rethrow(e);
inline function error(e : #if hscriptPos ErrorDef #else Error #end ) : Dynamic {
#if hscriptPos
throw new Error(e, curExpr.pmin, curExpr.pmax, curExpr.origin, curExpr.line);
#else
throw e;
#end
return null;
}
function resolve( id : String ) : Dynamic {
@@ -396,8 +385,7 @@ class Interp {
case EContinue:
throw SContinue;
case EReturn(e):
returnValue = e == null ? null : expr(e);
throw SReturn;
throw SReturn((e == null)?null:expr(e));
case EFunction(params,fexpr,name,_):
var capturedLocals = duplicate(locals);
var me = this;
@@ -572,8 +560,6 @@ class Interp {
if( !match )
val = def == null ? null : expr(def);
return val;
case EMeta(_, _, e):
return expr(e);
}
return null;
}
@@ -587,7 +573,7 @@ class Interp {
switch(err) {
case SContinue:
case SBreak: break;
case SReturn: throw err;
case SReturn(_): throw err;
}
}
}
@@ -604,7 +590,7 @@ class Interp {
switch(err) {
case SContinue:
case SBreak: break;
case SReturn: throw err;
case SReturn(_): throw err;
}
}
}
@@ -612,7 +598,7 @@ class Interp {
}
function makeIterator( v : Dynamic ) : Iterator<Dynamic> {
#if ((flash && !flash9) || (php && !php7 && haxe_ver < '4.0.0'))
#if ((flash && !flash9) || php)
if ( v.iterator != null ) v = v.iterator();
#else
try v = v.iterator() catch( e : Dynamic ) {};
@@ -633,7 +619,7 @@ class Interp {
switch( err ) {
case SContinue:
case SBreak: break;
case SReturn: throw err;
case SReturn(_): throw err;
}
}
}
+25 -32
View File
@@ -1,23 +1,26 @@
/*
* Copyright (C)2008-2017 Haxe Foundation
* Copyright (c) 2011, Nicolas Cannasse
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package hscript;
import hscript.Expr.Error;
@@ -76,9 +79,6 @@ class Macro {
#if haxe3
case OpArrow: "=>";
#end
#if (haxe_ver >= 4)
case OpIn: "in";
#end
};
binops.set(str, op);
if( assign )
@@ -129,10 +129,8 @@ class Macro {
TFunction(map(args,convertType), convertType(ret));
case CTAnon(fields):
var tf = [];
for( f in fields ) {
var meta = f.meta == null ? [] : [for( m in f.meta ) { name : m.name, params : m.params == null ? [] : [for( e in m.params ) convert(e)], pos : p }];
tf.push( { name : f.name, meta : meta, doc : null, access : [], kind : FVar(convertType(f.t), null), pos : p } );
}
for( f in fields )
tf.push( { name : f.name, meta : [], doc : null, access : [], kind : FVar(convertType(f.t),null), pos : p } );
TAnonymous(tf);
};
}
@@ -184,15 +182,13 @@ class Macro {
EWhile(convert(c), convert(e), true);
case EDoWhile(c, e):
EWhile(convert(c), convert(e), false);
#if (haxe_211 || haxe3)
case EFor(v, it, efor):
#if (haxe_ver >= 4)
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
EFor({ expr : EBinop(OpIn,{ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor));
#elseif (haxe_211 || haxe3)
var p = #if hscriptPos { file : p.file, min : e.pmin, max : e.pmax } #else p #end;
EFor({ expr : EIn({ expr : EConst(CIdent(v)), pos : p },convert(it)), pos : p }, convert(efor));
#else
EFor(v, convert(it), convert(efor));
case EFor(v, it, e):
EFor(v, convert(it), convert(e));
#end
case EBreak:
EBreak;
@@ -235,9 +231,6 @@ 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 }
}
+161 -573
View File
@@ -1,23 +1,26 @@
/*
* Copyright (C)2008-2017 Haxe Foundation
* Copyright (c) 2008, Nicolas Cannasse
* All rights reserved.
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
* - Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
* THIS SOFTWARE IS PROVIDED BY THE HAXE PROJECT CONTRIBUTORS "AS IS" AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE HAXE PROJECT CONTRIBUTORS BE LIABLE FOR
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*/
package hscript;
import hscript.Expr;
@@ -38,8 +41,6 @@ enum Token {
TBkClose;
TQuestion;
TDoubleDot;
TMeta( s : String );
TPrepro( s : String );
}
class Parser {
@@ -58,11 +59,6 @@ class Parser {
public var unops : Hash<Bool>; // true if allow postfix
#end
/**
allows to check for #if / #else in code
**/
public var preprocesorValues : Map<String,Dynamic> = new Map();
/**
activate JSON compatiblity
**/
@@ -73,11 +69,6 @@ class Parser {
**/
public var allowTypes : Bool;
/**
allow haxe metadata declarations
**/
public var allowMetadata : Bool;
// implementation
var input : haxe.io.Input;
var char : Int;
@@ -153,9 +144,13 @@ class Parser {
error(EInvalidChar(c), readPos, readPos);
}
function initParser( origin ) {
// line=1 - don't reset line : it might be set manualy
preprocStack = [];
public function parseString( s : String, ?origin : String = "hscript" ) {
uid = 0;
return parse( new haxe.io.StringInput(s), origin );
}
public function parse( s : haxe.io.Input, ?origin : String = "hscript" ) {
line = 1;
#if hscriptPos
this.origin = origin;
readPos = 0;
@@ -168,28 +163,19 @@ class Parser {
tokens = new haxe.FastList<Token>();
#end
char = -1;
input = s;
ops = new Array();
idents = new Array();
uid = 0;
for( i in 0...opChars.length )
ops[opChars.charCodeAt(i)] = true;
for( i in 0...identChars.length )
idents[identChars.charCodeAt(i)] = true;
}
public function parseString( s : String, ?origin : String = "hscript" ) {
return parse( new haxe.io.StringInput(s), origin );
}
public function parse( s : haxe.io.Input, ?origin : String = "hscript" ) {
initParser(origin);
input = s;
var a = new Array();
while( true ) {
var tk = token();
if( tk == TEof ) break;
push(tk);
parseFullExpr(a);
a.push(parseFullExpr());
}
return if( a.length == 1 ) a[0] else mk(EBlock(a),0);
}
@@ -214,29 +200,6 @@ class Parser {
if( t != tk ) unexpected(t);
}
inline function ensureToken(tk) {
var t = token();
if( !Type.enumEq(t,tk) ) unexpected(t);
}
function maybe(tk) {
var t = token();
if( Type.enumEq(t, tk) )
return true;
push(t);
return false;
}
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;
@@ -276,7 +239,7 @@ class Parser {
return switch( expr(e) ) {
case EBlock(_), EObject(_), ESwitch(_): true;
case EFunction(_,e,_,_): isBlock(e);
case EVar(_, t, e): e != null ? isBlock(e) : t != null ? t.match(CTAnon(_)) : false;
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);
@@ -285,29 +248,20 @@ class Parser {
case EFor(_,_,e): isBlock(e);
case EReturn(e): e != null && isBlock(e);
case ETry(_, _, _, e): isBlock(e);
case EMeta(_, _, e): isBlock(e);
default: false;
}
}
function parseFullExpr( exprs : Array<Expr> ) {
function parseFullExpr() {
var e = parseExpr();
exprs.push(e);
var tk = token();
// this is a hack to support var a,b,c; with a single EVar
while( tk == TComma && expr(e).match(EVar(_)) ) {
e = parseStructure("var"); // next variable
exprs.push(e);
tk = token();
}
if( tk != TSemicolon && tk != TEof ) {
if( isBlock(e) )
push(tk);
else
unexpected(tk);
}
return e;
}
function parseObject(p1) {
@@ -397,7 +351,7 @@ class Parser {
}
var a = new Array();
while( true ) {
parseFullExpr(a);
a.push(parseFullExpr());
tk = token();
if( tk == TBrClose )
break;
@@ -405,19 +359,8 @@ class Parser {
}
return mk(EBlock(a),p1);
case TOp(op):
if( unops.exists(op) ) {
var start = tokenMin;
var e = parseExpr();
if( op == "-" )
switch( expr(e) ) {
case EConst(CInt(i)):
return mk(EConst(CInt(-i)), start, pmax(e));
case EConst(CFloat(f)):
return mk(EConst(CFloat(-f)), start, pmax(e));
default:
}
return makeUnop(op,e);
}
if( unops.exists(op) )
return makeUnop(op,parseExpr());
return unexpected(tk);
case TBkOpen:
var a = new Array();
@@ -441,39 +384,12 @@ class Parser {
return parseExprNext(e);
default:
}
return parseExprNext(mk(EArrayDecl(a), p1));
case TMeta(id) if( allowMetadata ):
var args = parseMetaArgs();
return mk(EMeta(id, args, parseExpr()),p1);
return parseExprNext(mk(EArrayDecl(a),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):
@@ -544,8 +460,13 @@ 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();
@@ -573,8 +494,14 @@ class Parser {
mk(EDoWhile(econd,e),p1,pmax(econd));
case "for":
ensure(TPOpen);
var vname = getIdent();
ensureToken(TId("in"));
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);
var e = parseExpr();
@@ -582,9 +509,6 @@ class Parser {
case "break": mk(EBreak);
case "continue": mk(EContinue);
case "else": unexpected(TId(id));
case "inline":
if( !maybe(TId("function")) ) unexpected(TId("inline"));
return parseStructure("function");
case "function":
var tk = token();
var name = null;
@@ -592,8 +516,51 @@ class Parser {
case TId(id): name = id;
default: push(tk);
}
var inf = parseFunctionDecl();
mk(EFunction(inf.args, inf.body, name, inf.ret),p1,pmax(inf.body));
ensure(TPOpen);
var args = new Array();
tk = token();
if( tk != TPClose ) {
var done = false;
while( !done ) {
var name = null, opt = false;
switch( tk ) {
case TQuestion:
opt = true;
tk = token();
default:
}
switch( tk ) {
case TId(id): name = id;
default: unexpected(tk);
}
tk = token();
var arg : Argument = { name : name };
args.push(arg);
if( opt ) arg.opt = true;
if( tk == TDoubleDot && allowTypes ) {
arg.t = parseType();
tk = token();
}
switch( tk ) {
case TComma:
tk = token();
case TPClose:
done = true;
default:
unexpected(tk);
}
}
}
var ret = null;
if( allowTypes ) {
tk = token();
if( tk != TDoubleDot )
push(tk);
else
ret = parseType();
}
var body = parseExpr();
mk(EFunction(args, body, name, ret),p1,pmax(body));
case "return":
var tk = token();
push(tk);
@@ -601,13 +568,21 @@ class Parser {
mk(EReturn(e),p1,if( e == null ) tokenMax else pmax(e));
case "new":
var a = new Array();
a.push(getIdent());
var next = true;
while( next ) {
var tk = token();
switch( tk ) {
case TId(id): a.push(id);
default: unexpected(tk);
}
var next = true;
while( next ) {
tk = token();
switch( tk ) {
case TDot:
a.push(getIdent());
tk = token();
switch(tk) {
case TId(id): a.push(id);
default: unexpected(tk);
}
case TPOpen:
next = false;
default:
@@ -621,15 +596,22 @@ class Parser {
mk(EThrow(e),p1,pmax(e));
case "try":
var e = parseExpr();
ensureToken(TId("catch"));
var tk = token();
if( !Type.enumEq(tk, TId("catch")) ) unexpected(tk);
ensure(TPOpen);
var vname = getIdent();
tk = token();
var vname = switch( tk ) {
case TId(id): id;
default: unexpected(tk);
}
ensure(TDoubleDot);
var t = null;
if( allowTypes )
t = parseType();
else
ensureToken(TId("Dynamic"));
else {
tk = token();
if( !Type.enumEq(tk, TId("Dynamic")) ) unexpected(tk);
}
ensure(TPClose);
var ec = parseExpr();
mk(ETry(e, vname, t, ec), p1, pmax(ec));
@@ -664,7 +646,7 @@ class Parser {
case TId("case"), TId("default"), TBrClose:
break;
default:
parseFullExpr(exprs);
exprs.push(parseFullExpr());
}
}
c.expr = if( exprs.length == 1)
@@ -684,7 +666,7 @@ class Parser {
case TId("case"), TId("default"), TBrClose:
break;
default:
parseFullExpr(exprs);
exprs.push(parseFullExpr());
}
}
def = if( exprs.length == 1)
@@ -718,7 +700,12 @@ class Parser {
}
return makeBinop(op,e1,parseExpr());
case TDot:
var field = getIdent();
tk = token();
var field = null;
switch(tk) {
case TId(id): field = id;
default: unexpected(tk);
}
return parseExprNext(mk(EField(e1,field),pmin(e1)));
case TPOpen:
return parseExprNext(mk(ECall(e1,parseExprList(TPClose)),pmin(e1)));
@@ -737,76 +724,24 @@ class Parser {
}
}
function parseFunctionDecl() {
ensure(TPOpen);
var args = new Array();
var tk = token();
if( tk != TPClose ) {
var done = false;
while( !done ) {
var name = null, opt = false;
switch( tk ) {
case TQuestion:
opt = true;
tk = token();
default:
}
switch( tk ) {
case TId(id): name = id;
default: unexpected(tk);
}
var arg : Argument = { name : name };
args.push(arg);
if( opt ) arg.opt = true;
if( allowTypes ) {
if( maybe(TDoubleDot) )
arg.t = parseType();
if( maybe(TOp("=")) )
arg.value = parseExpr();
}
tk = token();
switch( tk ) {
case TComma:
tk = token();
case TPClose:
done = true;
default:
unexpected(tk);
}
}
}
var ret = null;
if( allowTypes ) {
tk = token();
if( tk != TDoubleDot )
push(tk);
else
ret = parseType();
}
return { args : args, ret : ret, body : parseExpr() };
}
function parsePath() {
var path = [getIdent()];
while( true ) {
var t = token();
if( t != TDot ) {
push(t);
break;
}
path.push(getIdent());
}
return path;
}
function parseType() : CType {
var t = token();
switch( t ) {
case TId(v):
push(t);
var path = parsePath();
var params = null;
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 == "<" ) {
@@ -842,29 +777,19 @@ 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(), meta : meta } );
fields.push( { name : name, t : parseType() } );
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);
}
@@ -916,210 +841,6 @@ class Parser {
return args;
}
// ------------------------ module -------------------------------
public function parseModule( content : String, ?origin : String = "hscript" ) {
initParser(origin);
this.input = new haxe.io.StringInput(content);
allowTypes = true;
allowMetadata = true;
var decls = [];
while( true ) {
var tk = token();
if( tk == TEof ) break;
push(tk);
decls.push(parseModuleDecl());
}
return decls;
}
function parseMetadata() : Metadata {
var meta = [];
while( true ) {
var tk = token();
switch( tk ) {
case TMeta(name):
meta.push({ name : name, params : parseMetaArgs() });
default:
push(tk);
break;
}
}
return meta;
}
function parseParams() {
if( maybe(TOp("<")) )
error(EInvalidOp("Unsupported class type parameters"), readPos, readPos);
return {};
}
function parseModuleDecl() : ModuleDecl {
var meta = parseMetadata();
var ident = getIdent();
var isPrivate = false, isExtern = false;
while( true ) {
switch( ident ) {
case "private":
isPrivate = true;
case "extern":
isExtern = true;
default:
break;
}
ident = getIdent();
}
switch( ident ) {
case "package":
var path = parsePath();
ensure(TSemicolon);
return DPackage(path);
case "import":
var path = [getIdent()];
var star = false;
while( true ) {
var t = token();
if( t != TDot ) {
push(t);
break;
}
t = token();
switch( t ) {
case TId(id):
path.push(id);
case TOp("*"):
star = true;
default:
unexpected(t);
}
}
ensure(TSemicolon);
return DImport(path, star);
case "class":
var name = getIdent();
var params = parseParams();
var extend = null;
var implement = [];
while( true ) {
var t = token();
switch( t ) {
case TId("extends"):
extend = parseType();
case TId("implements"):
implement.push(parseType());
default:
push(t);
break;
}
}
var fields = [];
ensure(TBrOpen);
while( !maybe(TBrClose) )
fields.push(parseField());
return DClass({
name : name,
meta : meta,
params : params,
extend : extend,
implement : implement,
fields : fields,
isPrivate : isPrivate,
isExtern : isExtern,
});
case "typedef":
var name = getIdent();
var params = parseParams();
ensureToken(TOp("="));
var t = parseType();
return DTypedef({
name : name,
meta : meta,
params : params,
isPrivate : isPrivate,
t : t,
});
default:
unexpected(TId(ident));
}
return null;
}
function parseField() : FieldDecl {
var meta = parseMetadata();
var access = [];
while( true ) {
var id = getIdent();
switch( id ) {
case "override":
access.push(AOverride);
case "public":
access.push(APublic);
case "private":
access.push(APrivate);
case "inline":
access.push(AInline);
case "static":
access.push(AStatic);
case "macro":
access.push(AMacro);
case "function":
var name = getIdent();
var inf = parseFunctionDecl();
return {
name : name,
meta : meta,
access : access,
kind : KFunction({
args : inf.args,
expr : inf.body,
ret : inf.ret,
}),
};
case "var":
var name = getIdent();
var get = null, set = null;
if( maybe(TPOpen) ) {
get = getIdent();
ensure(TComma);
set = getIdent();
ensure(TPClose);
}
var type = maybe(TDoubleDot) ? parseType() : null;
var expr = maybe(TOp("=")) ? parseExpr() : null;
if( expr != null ) {
if( isBlock(expr) )
maybe(TSemicolon);
else
ensure(TSemicolon);
} else if( type != null && type.match(CTAnon(_)) ) {
maybe(TSemicolon);
} else
ensure(TSemicolon);
return {
name : name,
meta : meta,
access : access,
kind : KVar({
get : get,
set : set,
type : type,
expr : expr,
}),
};
default:
unexpected(TId(id));
}
}
return null;
}
// ------------------------ lexing -------------------------------
inline function incPos() {
#if hscriptPos
readPos++;
@@ -1257,35 +978,18 @@ class Parser {
switch( char ) {
case 48,49,50,51,52,53,54,55,56,57:
n = n * 10 + (char - 48);
case "e".code, "E".code:
var tk = token();
var pow : Null<Int> = null;
switch( tk ) {
case TConst(CInt(e)): pow = e;
case TOp("-"):
tk = token();
switch( tk ) {
case TConst(CInt(e)): pow = -e;
default: push(tk);
}
default:
push(tk);
}
if( pow == null )
invalidChar(char);
return TConst(CFloat((Math.pow(10, pow) / exp) * n * 10));
case ".".code:
case 46:
if( exp > 0 ) {
// in case of '0...'
if( exp == 10 && readChar() == ".".code ) {
// in case of '...'
if( exp == 10 && readChar() == 46 ) {
push(TOp("..."));
var i = Std.int(n);
var i = Std.int(n) & 0xFFFFFFFF;
return TConst( (i == n) ? CInt(i) : CFloat(n) );
}
invalidChar(char);
}
exp = 1.;
case "x".code:
case 120: // x
if( n > 0 || exp > 0 )
invalidChar(char);
// read hexa
@@ -1302,7 +1006,7 @@ class Parser {
n = (n << 4) + (char - 87);
default:
this.char = char;
return TConst(CInt(n));
return TConst(CInt(n & 0xFFFFFFFF));
}
}
#else
@@ -1332,11 +1036,11 @@ class Parser {
return TConst( (exp > 0) ? CFloat(n * 10 / exp) : ((i == n) ? CInt(i) : CFloat(n)) );
}
}
case ";".code: return TSemicolon;
case "(".code: return TPOpen;
case ")".code: return TPClose;
case ",".code: return TComma;
case ".".code:
case 59: return TSemicolon;
case 40: return TPOpen;
case 41: return TPClose;
case 44: return TComma;
case 46:
char = readChar();
switch( char ) {
case 48,49,50,51,52,53,54,55,56,57:
@@ -1353,22 +1057,23 @@ class Parser {
return TConst( CFloat(n/exp) );
}
}
case ".".code:
case 46:
char = readChar();
if( char != ".".code )
if( char != 46 )
invalidChar(char);
return TOp("...");
default:
this.char = char;
return TDot;
}
case "{".code: return TBrOpen;
case "}".code: return TBrClose;
case "[".code: return TBkOpen;
case "]".code: return TBkClose;
case "'".code, '"'.code: return TConst( CString(readString(char)) );
case "?".code: return TQuestion;
case ":".code: return TDoubleDot;
case 123: return TBrOpen;
case 125: return TBrClose;
case 91: return TBkOpen;
case 93: return TBkClose;
case 39: return TConst( CString(readString(39)) );
case 34: return TConst( CString(readString(34)) );
case 63: return TQuestion;
case 58: return TDoubleDot;
case '='.code:
char = readChar();
if( char == '='.code )
@@ -1377,34 +1082,6 @@ 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);
case '#'.code:
char = readChar();
if( idents[char] ) {
var id = String.fromCharCode(char);
while( true ) {
char = readChar();
if( !idents[char] ) {
this.char = char;
return preprocess(id);
}
id += String.fromCharCode(char);
}
}
invalidChar(char);
default:
if( ops[char] ) {
var op = String.fromCharCode(char);
@@ -1439,93 +1116,6 @@ class Parser {
return null;
}
function preprocValue( id : String ) : Dynamic {
return preprocesorValues.get(id);
}
var preprocStack : Array<{ r : Bool }>;
function parsePreproCond() {
var tk = token();
return switch( tk ) {
case TPOpen:
push(TPOpen);
parseExpr();
case TId(id):
mk(EIdent(id), tokenMin, tokenMax);
case TOp("!"):
mk(EUnop("!", true, parsePreproCond()), tokenMin, tokenMax);
default:
unexpected(tk);
}
}
function evalPreproCond( e : Expr ) {
switch( expr(e) ) {
case EIdent(id):
return preprocValue(id) != null;
case EUnop("!", _, e):
return !evalPreproCond(e);
case EParent(e):
return evalPreproCond(e);
case EBinop("&&", e1, e2):
return evalPreproCond(e1) && evalPreproCond(e2);
case EBinop("||", e1, e2):
return evalPreproCond(e1) || evalPreproCond(e2);
default:
error(EInvalidPreprocessor("Can't eval " + expr(e).getName()), readPos, readPos);
return false;
}
}
function preprocess( id : String ) : Token {
switch( id ) {
case "if":
var e = parsePreproCond();
if( evalPreproCond(e) ) {
preprocStack.push({ r : true });
return token();
}
preprocStack.push({ r : false });
skipTokens();
return token();
case "else", "elseif" if( preprocStack.length > 0 ):
if( preprocStack[preprocStack.length - 1].r ) {
preprocStack[preprocStack.length - 1].r = false;
skipTokens();
return token();
} else if( id == "else" ) {
preprocStack.pop();
preprocStack.push({ r : true });
return token();
} else {
// elseif
preprocStack.pop();
return preprocess("if");
}
case "end" if( preprocStack.length > 0 ):
preprocStack.pop();
return token();
default:
return TPrepro(id);
}
}
function skipTokens() {
var spos = preprocStack.length - 1;
var obj = preprocStack[spos];
var pos = readPos;
while( true ) {
var tk = token();
if( tk == TEof )
error(EInvalidPreprocessor("Unclosed"), pos, pos);
if( preprocStack[spos] != obj ) {
push(tk);
break;
}
}
}
function tokenComment( op : String, char : Int ) {
var c = op.charCodeAt(1);
var s = input;
@@ -1596,8 +1186,6 @@ class Parser {
case TBkClose: "]";
case TQuestion: "?";
case TDoubleDot: ":";
case TMeta(id): "@" + id;
case TPrepro(id): "#" + id;
}
}
-63
View File
@@ -1,24 +1,3 @@
/*
* Copyright (C)2008-2017 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
import hscript.Expr;
@@ -37,13 +16,6 @@ class Printer {
return buf.toString();
}
public function typeToString( t : CType ) {
buf = new StringBuf();
tabs = "";
type(t);
return buf.toString();
}
inline function add<T>(s:T) buf.add(s);
function type( t : CType ) {
@@ -286,20 +258,6 @@ class Printer {
add(";\n");
}
add("}");
case EMeta(name, args, e):
add("@");
add(name);
if( args != null && args.length > 0 ) {
add("(");
var first = true;
for( a in args ) {
if( first ) first = false else add(", ");
expr(e);
}
add(")");
}
add(" ");
expr(e);
}
}
@@ -307,25 +265,4 @@ class Printer {
return new Printer().exprToString(e);
}
public static function errorToString( e : Expr.Error ) {
var message = switch( #if hscriptPos e.e #else e #end ) {
case EInvalidChar(c): "Invalid character: '"+String.fromCharCode(c)+"' ("+c+")";
case EUnexpected(s): "Unexpected token: \""+s+"\"";
case EUnterminatedString: "Unterminated string";
case EUnterminatedComment: "Unterminated comment";
case EInvalidPreprocessor(str): "Invalid preprocessor (" + str + ")";
case EUnknownVariable(v): "Unknown variable: "+v;
case EInvalidIterator(v): "Invalid iterator: "+v;
case EInvalidOp(op): "Invalid operator: "+op;
case EInvalidAccess(f): "Invalid access to field " + f;
case ECustom(msg): msg;
};
#if hscriptPos
return e.origin + ":" + e.line + ": " + message;
#else
return message;
#end
}
}
+3 -32
View File
@@ -1,31 +1,10 @@
/*
* Copyright (C)2008-2017 Haxe Foundation
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
package hscript;
import hscript.Expr;
class Tools {
public static function iter( e : Expr, f : Expr -> Void ) {
switch( #if hscriptPos e.e #else e #end ) {
switch( e ) {
case EConst(_), EIdent(_):
case EVar(_, _, e): if( e != null ) f(e);
case EParent(e): f(e);
@@ -55,17 +34,12 @@ class Tools {
f(c.expr);
}
if( def != null ) f(def);
case EMeta(name, args, e): if( args != null ) for( a in args ) f(a); f(e);
}
}
public static function map( e : Expr, f : Expr -> Expr ) {
#if hscriptPos
var edef = switch( e.e ) {
#else
return switch( e ) {
#end
case EConst(_), EIdent(_), EBreak, EContinue: #if hscriptPos e.e #else e #end;
case EConst(_), EIdent(_): e;
case EVar(n, t, e): EVar(n, t, if( e != null ) f(e) else null);
case EParent(e): EParent(f(e));
case EBlock(el): EBlock([for( e in el ) f(e)]);
@@ -77,6 +51,7 @@ class Tools {
case EWhile(c, e): EWhile(f(c),f(e));
case EDoWhile(c, e): EDoWhile(f(c),f(e));
case EFor(v, it, e): EFor(v, f(it), f(e));
case EBreak, EContinue: e;
case EFunction(args, e, name, t): EFunction(args, f(e), name, t);
case EReturn(e): EReturn(if( e != null ) f(e) else null);
case EArray(e, i): EArray(f(e),f(i));
@@ -87,11 +62,7 @@ class Tools {
case EObject(fl): EObject([for( fi in fl ) { name : fi.name, e : f(fi.e) }]);
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));
}
#if hscriptPos
return { e : edef, pmin : e.pmin, pmax : e.pmax, origin : e.origin, line : e.line };
#end
}
}