pass typed data back and forth with #extern. close #17
This commit is contained in:
@@ -466,19 +466,37 @@ class Helpers {
|
|||||||
// Return convenient functions for succinctly making new ReaderExps that link back to an original exp's
|
// Return convenient functions for succinctly making new ReaderExps that link back to an original exp's
|
||||||
// position in source code
|
// position in source code
|
||||||
public static function expBuilder(posRef:ReaderExp) {
|
public static function expBuilder(posRef:ReaderExp) {
|
||||||
|
function _symbol(?name:String) {
|
||||||
|
return Prelude.symbol(name).withPosOf(posRef);
|
||||||
|
}
|
||||||
|
function call(func:ReaderExp, args:Array<ReaderExp>) {
|
||||||
|
return CallExp(func, args).withPosOf(posRef);
|
||||||
|
}
|
||||||
|
function callSymbol(symbol:String, args:Array<ReaderExp>) {
|
||||||
|
return call(_symbol(symbol), args);
|
||||||
|
}
|
||||||
|
function field(f:String, exp:ReaderExp) {
|
||||||
|
return FieldExp(f, exp).withPosOf(posRef);
|
||||||
|
}
|
||||||
|
function list(exps:Array<ReaderExp>) {
|
||||||
|
return ListExp(exps).withPosOf(posRef);
|
||||||
|
}
|
||||||
return {
|
return {
|
||||||
call: (func:ReaderExp, args:Array<ReaderExp>) -> CallExp(func, args).withPosOf(posRef),
|
call: call,
|
||||||
callSymbol: (symbol:String, args:Array<ReaderExp>) -> CallExp(Symbol(symbol).withPosOf(posRef), args).withPosOf(posRef),
|
callSymbol: callSymbol,
|
||||||
|
callField: (fieldName:String, callOn:ReaderExp, args:Array<ReaderExp>) -> call(field(fieldName, callOn), args),
|
||||||
print: (arg:ReaderExp) -> CallExp(Symbol("print").withPosOf(posRef), [arg]).withPosOf(posRef),
|
print: (arg:ReaderExp) -> CallExp(Symbol("print").withPosOf(posRef), [arg]).withPosOf(posRef),
|
||||||
list: (exps:Array<ReaderExp>) -> ListExp(exps).withPosOf(posRef),
|
the: (type:ReaderExp, value:ReaderExp) -> callSymbol("the", [type, value]),
|
||||||
|
list: list,
|
||||||
str: (s:String) -> StrExp(s).withPosOf(posRef),
|
str: (s:String) -> StrExp(s).withPosOf(posRef),
|
||||||
symbol: (?name:String) -> Prelude.symbol(name).withPosOf(posRef),
|
symbol: _symbol,
|
||||||
raw: (code:String) -> RawHaxe(code).withPosOf(posRef),
|
raw: (code:String) -> RawHaxe(code).withPosOf(posRef),
|
||||||
typed: (path:String, exp:ReaderExp) -> TypedExp(path, exp).withPosOf(posRef),
|
typed: (path:String, exp:ReaderExp) -> TypedExp(path, exp).withPosOf(posRef),
|
||||||
meta: (m:String, exp:ReaderExp) -> MetaExp(m, exp).withPosOf(posRef),
|
meta: (m:String, exp:ReaderExp) -> MetaExp(m, exp).withPosOf(posRef),
|
||||||
field: (f:String, exp:ReaderExp) -> FieldExp(f, exp).withPosOf(posRef),
|
field: field,
|
||||||
keyValue: (key:ReaderExp, value:ReaderExp) -> KeyValueExp(key, value).withPosOf(posRef),
|
keyValue: (key:ReaderExp, value:ReaderExp) -> KeyValueExp(key, value).withPosOf(posRef),
|
||||||
begin: (exps:Array<ReaderExp>) -> CallExp(Symbol("begin").withPosOf(posRef), exps).withPosOf(posRef),
|
begin: (exps:Array<ReaderExp>) -> callSymbol("begin", exps),
|
||||||
|
let: (bindings:Array<ReaderExp>, body:Array<ReaderExp>) -> callSymbol("let", [list(bindings)].concat(body)),
|
||||||
none: () -> None.withPosOf(posRef)
|
none: () -> None.withPosOf(posRef)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@@ -809,25 +809,49 @@ class Macros {
|
|||||||
{};
|
{};
|
||||||
}
|
}
|
||||||
|
|
||||||
trace(compileArgs);
|
|
||||||
trace(bindingListExp);
|
|
||||||
// TODO generate tink_json writers and parsers for this
|
|
||||||
|
|
||||||
var b = wholeExp.expBuilder();
|
var b = wholeExp.expBuilder();
|
||||||
|
|
||||||
|
// TODO generate tink_json writers and parsers for this
|
||||||
|
var bindingList = bindingListExp.bindingList("#extern", true);
|
||||||
|
|
||||||
|
var idx = 0;
|
||||||
|
var stringifyExpList = [];
|
||||||
|
var parseBindingList = [];
|
||||||
|
while (idx < bindingList.length) {
|
||||||
|
var type = "";
|
||||||
|
var untypedName = switch (bindingList[idx].def) {
|
||||||
|
case TypedExp(_type, symbol = {pos: _, def: Symbol(name)}):
|
||||||
|
type = _type;
|
||||||
|
symbol;
|
||||||
|
default: throw CompileError.fromExp(bindingList[idx], "name in #extern binding list must be a typed symbol");
|
||||||
|
};
|
||||||
|
switch (bindingList[idx + 1].def) {
|
||||||
|
// _ in the value position of the #extern binding list will reuse the name as the value
|
||||||
|
case Symbol("_"):
|
||||||
|
bindingList[idx + 1] = untypedName;
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
stringifyExpList.push(b.callSymbol("tink.Json.stringify", [b.the(b.symbol(type), bindingList[idx + 1])]));
|
||||||
|
parseBindingList.push(bindingList[idx]);
|
||||||
|
parseBindingList.push(b.callSymbol("tink.Json.parse", [b.callField("readLine", b.callSymbol("Sys.stdin", []), [])]));
|
||||||
|
idx += 2;
|
||||||
|
}
|
||||||
|
|
||||||
var externExps = [
|
var externExps = [
|
||||||
b.print(
|
b.print(
|
||||||
b.callSymbol("tink.Json.stringify", [
|
b.callSymbol("tink.Json.stringify", [
|
||||||
b.callSymbol("the", [
|
b.the(bodyType, if (bindingList.length > 0) {
|
||||||
bodyType, b.begin(exps)
|
b.let(parseBindingList, exps);
|
||||||
])
|
} else {
|
||||||
|
b.begin(exps);
|
||||||
|
})
|
||||||
]))
|
]))
|
||||||
];
|
];
|
||||||
b.callSymbol("the", [
|
b.the(
|
||||||
bodyType,
|
bodyType,
|
||||||
b.callSymbol("tink.Json.parse", [
|
b.callSymbol("tink.Json.parse", [
|
||||||
b.call(b.raw(CompilerTools.compileToScript(externExps, langArg, compileArgs).toString()), [])
|
b.call(b.raw(CompilerTools.compileToScript(externExps, langArg, compileArgs).toString()), [b.list(stringifyExpList)])
|
||||||
])
|
]));
|
||||||
]);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
return macros;
|
return macros;
|
||||||
|
@@ -7,6 +7,7 @@ import kiss.Prelude;
|
|||||||
|
|
||||||
@:build(kiss.Kiss.build())
|
@:build(kiss.Kiss.build())
|
||||||
class ExternTestCase extends Test {
|
class ExternTestCase extends Test {
|
||||||
|
#if (sys || hxnodejs)
|
||||||
function testExternPython() {
|
function testExternPython() {
|
||||||
_testExternPython();
|
_testExternPython();
|
||||||
}
|
}
|
||||||
@@ -14,4 +15,5 @@ class ExternTestCase extends Test {
|
|||||||
function testExternJavaScript() {
|
function testExternJavaScript() {
|
||||||
_testExternJavaScript();
|
_testExternJavaScript();
|
||||||
}
|
}
|
||||||
|
#end
|
||||||
}
|
}
|
||||||
|
@@ -1,13 +1,10 @@
|
|||||||
(function _testExternPython []
|
(function _testExternPython []
|
||||||
(Assert.isTrue
|
(Assert.isTrue
|
||||||
(#extern Bool python []
|
(#extern Bool python [:String passingString "Hello python!"]
|
||||||
(#if python
|
(python.NativeStringTools.startswith passingString "Hello"))))
|
||||||
true
|
|
||||||
false))))
|
|
||||||
|
|
||||||
(function _testExternJavaScript []
|
(function _testExternJavaScript []
|
||||||
(Assert.isTrue
|
(Assert.equals 18
|
||||||
(#extern Bool js []
|
(let [jsToEval "5+6+7"]
|
||||||
(#if js
|
(#extern Int js [:String jsToEval _]
|
||||||
true
|
(js.Lib.eval jsToEval)))))
|
||||||
false))))
|
|
Reference in New Issue
Block a user