Add positions to ReaderExp
This commit is contained in:
@@ -5,11 +5,13 @@ import haxe.macro.Context;
|
|||||||
import kiss.Reader;
|
import kiss.Reader;
|
||||||
import kiss.Types;
|
import kiss.Types;
|
||||||
import kiss.Helpers;
|
import kiss.Helpers;
|
||||||
|
import kiss.Stream;
|
||||||
|
|
||||||
|
using kiss.Reader;
|
||||||
using StringTools;
|
using StringTools;
|
||||||
|
|
||||||
// Field forms convert Kiss reader expressions into Haxe macro class fields
|
// Field forms convert Kiss reader expressions into Haxe macro class fields
|
||||||
typedef FieldFormFunction = (position:String, args:Array<ReaderExp>, convert:ExprConversion) -> Field;
|
typedef FieldFormFunction = (pos:Position, args:Array<ReaderExp>, convert:ExprConversion) -> Field;
|
||||||
|
|
||||||
class FieldForms {
|
class FieldForms {
|
||||||
public static function builtins() {
|
public static function builtins() {
|
||||||
@@ -33,27 +35,27 @@ class FieldForms {
|
|||||||
return access;
|
return access;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function fieldName(formName:String, position:String, nameExp:ReaderExp) {
|
static function fieldName(formName:String, nameExp:ReaderExp) {
|
||||||
return switch (nameExp) {
|
return switch (nameExp.def) {
|
||||||
case Symbol(name) | TypedExp(_, Symbol(name)):
|
case Symbol(name) | TypedExp(_, {pos: _, def: Symbol(name)}):
|
||||||
name;
|
name;
|
||||||
default:
|
default:
|
||||||
throw 'The first argument to $formName at $position should be a variable name or typed variable name';
|
throw 'The first argument to $formName at ${nameExp.pos} should be a variable name or typed variable name';
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
static function varOrProperty(formName:String, position:String, args:Array<ReaderExp>, convert:ExprConversion):Field {
|
static function varOrProperty(formName:String, position:Position, args:Array<ReaderExp>, convert:ExprConversion):Field {
|
||||||
if (args.length != 2) {
|
if (args.length != 2) {
|
||||||
throw '$formName with $args at $position is not a valid field definition';
|
throw '$formName with $args at $position is not a valid field definition';
|
||||||
}
|
}
|
||||||
|
|
||||||
var name = fieldName(formName, position, args[0]);
|
var name = fieldName(formName, args[0]);
|
||||||
var access = fieldAccess(formName, name);
|
var access = fieldAccess(formName, name);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
name: name,
|
name: name,
|
||||||
access: access,
|
access: access,
|
||||||
kind: FVar(switch (args[0]) {
|
kind: FVar(switch (args[0].def) {
|
||||||
case TypedExp(type, _):
|
case TypedExp(type, _):
|
||||||
Helpers.parseComplexType(type);
|
Helpers.parseComplexType(type);
|
||||||
default: null;
|
default: null;
|
||||||
@@ -63,12 +65,12 @@ class FieldForms {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// TODO &rest, &body and &optional arguments
|
// TODO &rest, &body and &optional arguments
|
||||||
static function funcOrMethod(formName:String, position:String, args:Array<ReaderExp>, convert:ExprConversion):Field {
|
static function funcOrMethod(formName:String, position:Position, args:Array<ReaderExp>, convert:ExprConversion):Field {
|
||||||
if (args.length <= 2) {
|
if (args.length <= 2) {
|
||||||
throw '$formName with $args is not a valid function/method definition';
|
throw '$formName with $args is not a valid function/method definition';
|
||||||
}
|
}
|
||||||
|
|
||||||
var name = fieldName(formName, position, args[0]);
|
var name = fieldName(formName, args[0]);
|
||||||
var access = fieldAccess(formName, name);
|
var access = fieldAccess(formName, name);
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -76,19 +78,19 @@ class FieldForms {
|
|||||||
access: access,
|
access: access,
|
||||||
// TODO type parameter declarations
|
// TODO type parameter declarations
|
||||||
kind: FFun({
|
kind: FFun({
|
||||||
args: switch (args[1]) {
|
args: switch (args[1].def) {
|
||||||
case ListExp(funcArgs):
|
case ListExp(funcArgs):
|
||||||
[
|
[
|
||||||
// TODO optional arguments, default values
|
// TODO optional arguments, default values
|
||||||
for (funcArg in funcArgs)
|
for (funcArg in funcArgs)
|
||||||
{
|
{
|
||||||
name: switch (funcArg) {
|
name: switch (funcArg.def) {
|
||||||
case Symbol(name) | TypedExp(_, Symbol(name)):
|
case Symbol(name) | TypedExp(_, {pos: _, def: Symbol(name)}):
|
||||||
name;
|
name;
|
||||||
default:
|
default:
|
||||||
throw '$funcArg should be a symbol or typed symbol for a function argument';
|
throw '$funcArg should be a symbol or typed symbol for a function argument';
|
||||||
},
|
},
|
||||||
type: switch (funcArg) {
|
type: switch (funcArg.def) {
|
||||||
case TypedExp(type, _):
|
case TypedExp(type, _):
|
||||||
Helpers.parseComplexType(type);
|
Helpers.parseComplexType(type);
|
||||||
default: null;
|
default: null;
|
||||||
@@ -100,13 +102,13 @@ class FieldForms {
|
|||||||
default:
|
default:
|
||||||
throw '${args[1]} should be an argument list';
|
throw '${args[1]} should be an argument list';
|
||||||
},
|
},
|
||||||
ret: switch (args[0]) {
|
ret: switch (args[0].def) {
|
||||||
case TypedExp(type, _): Helpers.parseComplexType(type);
|
case TypedExp(type, _): Helpers.parseComplexType(type);
|
||||||
default: null;
|
default: null;
|
||||||
},
|
},
|
||||||
expr: {
|
expr: {
|
||||||
pos: Context.currentPos(),
|
pos: Context.currentPos(),
|
||||||
expr: EReturn(convert(CallExp(Symbol("begin"), args.slice(2))))
|
expr: EReturn(convert(CallExp(Symbol("begin").withPos(args[2].pos), args.slice(2)).withPos(args[2].pos)))
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
pos: Context.currentPos()
|
pos: Context.currentPos()
|
||||||
|
|||||||
@@ -62,17 +62,17 @@ class Kiss {
|
|||||||
return classFields;
|
return classFields;
|
||||||
}
|
}
|
||||||
|
|
||||||
static function readerExpToField(exp:ReaderExp, position:String, k:KissState):Null<Field> {
|
static function readerExpToField(exp:ReaderExp, position:Position, k:KissState):Null<Field> {
|
||||||
var fieldForms = k.fieldForms;
|
var fieldForms = k.fieldForms;
|
||||||
|
|
||||||
// Macros at top-level are allowed if they expand into a fieldform, or null like defreadermacro
|
// Macros at top-level are allowed if they expand into a fieldform, or null like defreadermacro
|
||||||
var macros = k.macros;
|
var macros = k.macros;
|
||||||
|
|
||||||
return switch (exp) {
|
return switch (exp.def) {
|
||||||
case CallExp(Symbol(mac), args) if (macros.exists(mac)):
|
case CallExp({pos: _, def: Symbol(mac)}, args) if (macros.exists(mac)):
|
||||||
var expandedExp = macros[mac](args, k);
|
var expandedExp = macros[mac](args, k);
|
||||||
if (expandedExp != null) readerExpToField(macros[mac](args, k), position, k) else null;
|
if (expandedExp != null) readerExpToField(macros[mac](args, k), position, k) else null;
|
||||||
case CallExp(Symbol(formName), args) if (fieldForms.exists(formName)):
|
case CallExp({pos: _, def: Symbol(formName)}, args) if (fieldForms.exists(formName)):
|
||||||
fieldForms[formName](position, args, readerExpToHaxeExpr.bind(_, k));
|
fieldForms[formName](position, args, readerExpToHaxeExpr.bind(_, k));
|
||||||
default:
|
default:
|
||||||
throw '$exp at $position is not a valid field form';
|
throw '$exp at $position is not a valid field form';
|
||||||
@@ -84,7 +84,7 @@ class Kiss {
|
|||||||
var specialForms = k.specialForms;
|
var specialForms = k.specialForms;
|
||||||
// Bind the table arguments of this function for easy recursive calling/passing
|
// Bind the table arguments of this function for easy recursive calling/passing
|
||||||
var convert = readerExpToHaxeExpr.bind(_, k);
|
var convert = readerExpToHaxeExpr.bind(_, k);
|
||||||
var expr = switch (exp) {
|
var expr = switch (exp.def) {
|
||||||
case Symbol(name):
|
case Symbol(name):
|
||||||
Context.parse(name, Context.currentPos());
|
Context.parse(name, Context.currentPos());
|
||||||
case StrExp(s):
|
case StrExp(s):
|
||||||
@@ -92,9 +92,9 @@ class Kiss {
|
|||||||
pos: Context.currentPos(),
|
pos: Context.currentPos(),
|
||||||
expr: EConst(CString(s))
|
expr: EConst(CString(s))
|
||||||
};
|
};
|
||||||
case CallExp(Symbol(mac), args) if (macros.exists(mac)):
|
case CallExp({pos: _, def: Symbol(mac)}, args) if (macros.exists(mac)):
|
||||||
convert(macros[mac](args, k));
|
convert(macros[mac](args, k));
|
||||||
case CallExp(Symbol(specialForm), args) if (specialForms.exists(specialForm)):
|
case CallExp({pos: _, def: Symbol(specialForm)}, args) if (specialForms.exists(specialForm)):
|
||||||
specialForms[specialForm](args, convert);
|
specialForms[specialForm](args, convert);
|
||||||
case CallExp(func, body):
|
case CallExp(func, body):
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import hscript.Interp;
|
|||||||
import kiss.Reader;
|
import kiss.Reader;
|
||||||
import kiss.Kiss;
|
import kiss.Kiss;
|
||||||
|
|
||||||
|
using kiss.Reader;
|
||||||
using kiss.Helpers;
|
using kiss.Helpers;
|
||||||
|
|
||||||
// Macros generate new Kiss reader expressions from the arguments of their call expression.
|
// Macros generate new Kiss reader expressions from the arguments of their call expression.
|
||||||
@@ -28,14 +29,14 @@ class Macros {
|
|||||||
if (exps.length != 2) {
|
if (exps.length != 2) {
|
||||||
throw 'Got ${exps.length} arguments for % instead of 2.';
|
throw 'Got ${exps.length} arguments for % instead of 2.';
|
||||||
}
|
}
|
||||||
CallExp(Symbol("Prelude.mod"), [exps[1], exps[0]]);
|
CallExp(Symbol("Prelude.mod").withPos(exps[0].pos), [exps[1], exps[0]]).withPos(exps[0].pos);
|
||||||
};
|
};
|
||||||
|
|
||||||
macros["^"] = (exps:Array<ReaderExp>, k) -> {
|
macros["^"] = (exps:Array<ReaderExp>, k) -> {
|
||||||
if (exps.length != 2) {
|
if (exps.length != 2) {
|
||||||
throw 'Got ${exps.length} arguments for ^ instead of 2.';
|
throw 'Got ${exps.length} arguments for ^ instead of 2.';
|
||||||
}
|
}
|
||||||
CallExp(Symbol("Prelude.pow"), [exps[1], exps[0]]);
|
CallExp(Symbol("Prelude.pow").withPos(exps[0].pos), [exps[1], exps[0]]).withPos(exps[0].pos);
|
||||||
};
|
};
|
||||||
|
|
||||||
macros["min"] = foldMacro("Prelude.minInclusive");
|
macros["min"] = foldMacro("Prelude.minInclusive");
|
||||||
@@ -54,7 +55,7 @@ class Macros {
|
|||||||
macros["defmacrofun"] = (exps:Array<ReaderExp>, k:KissState) -> {
|
macros["defmacrofun"] = (exps:Array<ReaderExp>, k:KissState) -> {
|
||||||
if (exps.length < 3)
|
if (exps.length < 3)
|
||||||
throw '${exps.length} is not enough arguments for (defmacrofun [name] [args] [body])';
|
throw '${exps.length} is not enough arguments for (defmacrofun [name] [args] [body])';
|
||||||
var macroName = switch (exps[0]) {
|
var macroName = switch (exps[0].def) {
|
||||||
case Symbol(name): name;
|
case Symbol(name): name;
|
||||||
default: throw 'first argument ${exps[0]} for defmacrofun should be a symbol for the macro name';
|
default: throw 'first argument ${exps[0]} for defmacrofun should be a symbol for the macro name';
|
||||||
};
|
};
|
||||||
@@ -69,7 +70,7 @@ class Macros {
|
|||||||
]).withContextPos();
|
]).withContextPos();
|
||||||
};
|
};
|
||||||
|
|
||||||
CallExp(Symbol("defun"), exps);
|
CallExp(Symbol("defun").withPos(exps[0].pos), exps).withPos(exps[0].pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
// For now, reader macros only support a one-expression body implemented in #|raw haxe|#
|
// For now, reader macros only support a one-expression body implemented in #|raw haxe|#
|
||||||
@@ -77,16 +78,16 @@ class Macros {
|
|||||||
if (exps.length != 3) {
|
if (exps.length != 3) {
|
||||||
throw 'wrong number of expressions for defreadermacro: $exps should be String, [streamArgName], RawHaxe';
|
throw 'wrong number of expressions for defreadermacro: $exps should be String, [streamArgName], RawHaxe';
|
||||||
}
|
}
|
||||||
switch (exps[0]) {
|
switch (exps[0].def) {
|
||||||
case StrExp(s):
|
case StrExp(s):
|
||||||
switch (exps[1]) {
|
switch (exps[1].def) {
|
||||||
case ListExp([Symbol(streamArgName)]):
|
case ListExp([{pos: _, def: Symbol(streamArgName)}]):
|
||||||
switch (exps[2]) {
|
switch (exps[2].def) {
|
||||||
case RawHaxe(code):
|
case RawHaxe(code):
|
||||||
k.readTable[s] = (stream) -> {
|
k.readTable[s] = (stream) -> {
|
||||||
var parser = new Parser();
|
var parser = new Parser();
|
||||||
var interp = new Interp();
|
var interp = new Interp();
|
||||||
interp.variables.set("ReaderExp", ReaderExp);
|
interp.variables.set("ReaderExp", ReaderExpDef);
|
||||||
interp.variables.set(streamArgName, stream);
|
interp.variables.set(streamArgName, stream);
|
||||||
interp.execute(parser.parseString(code));
|
interp.execute(parser.parseString(code));
|
||||||
};
|
};
|
||||||
@@ -107,8 +108,12 @@ class Macros {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static function foldMacro(func:String):MacroFunction {
|
static function foldMacro(func:String):MacroFunction {
|
||||||
return (exps, k) -> {
|
return (exps:Array<ReaderExp>, k) -> {
|
||||||
CallExp(Symbol("Lambda.fold"), [ListExp(exps.slice(1)), Symbol(func), exps[0]]);
|
CallExp(Symbol("Lambda.fold").withPos(exps[0].pos), [
|
||||||
|
ListExp(exps.slice(1)).withPos(exps[0].pos),
|
||||||
|
Symbol(func).withPos(exps[0].pos),
|
||||||
|
exps[0]
|
||||||
|
]).withPos(exps[0].pos);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,7 +3,14 @@ package kiss;
|
|||||||
import haxe.ds.Option;
|
import haxe.ds.Option;
|
||||||
import kiss.Stream;
|
import kiss.Stream;
|
||||||
|
|
||||||
enum ReaderExp {
|
using kiss.Reader;
|
||||||
|
|
||||||
|
typedef ReaderExp = {
|
||||||
|
pos:Position,
|
||||||
|
def:ReaderExpDef
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ReaderExpDef {
|
||||||
CallExp(func:ReaderExp, args:Array<ReaderExp>); // (f a1 a2...)
|
CallExp(func:ReaderExp, args:Array<ReaderExp>); // (f a1 a2...)
|
||||||
ListExp(exps:Array<ReaderExp>); // [v1 v2 v3]
|
ListExp(exps:Array<ReaderExp>); // [v1 v2 v3]
|
||||||
StrExp(s:String); // "literal"
|
StrExp(s:String); // "literal"
|
||||||
@@ -12,7 +19,7 @@ enum ReaderExp {
|
|||||||
TypedExp(path:String, exp:ReaderExp); // :type [exp]
|
TypedExp(path:String, exp:ReaderExp); // :type [exp]
|
||||||
}
|
}
|
||||||
|
|
||||||
typedef ReadFunction = (Stream) -> Null<ReaderExp>;
|
typedef ReadFunction = (Stream) -> Null<ReaderExpDef>;
|
||||||
|
|
||||||
class Reader {
|
class Reader {
|
||||||
// The built-in readtable
|
// The built-in readtable
|
||||||
@@ -64,6 +71,7 @@ class Reader {
|
|||||||
if (stream.isEmpty())
|
if (stream.isEmpty())
|
||||||
return None;
|
return None;
|
||||||
|
|
||||||
|
var position = stream.position();
|
||||||
var readTableKeys = [for (key in readTable.keys()) key];
|
var readTableKeys = [for (key in readTable.keys()) key];
|
||||||
readTableKeys.sort((a, b) -> b.length - a.length);
|
readTableKeys.sort((a, b) -> b.length - a.length);
|
||||||
|
|
||||||
@@ -72,7 +80,11 @@ class Reader {
|
|||||||
case Some(k) if (k == key):
|
case Some(k) if (k == key):
|
||||||
stream.dropString(key);
|
stream.dropString(key);
|
||||||
var expOrNull = readTable[key](stream);
|
var expOrNull = readTable[key](stream);
|
||||||
return if (expOrNull != null) Some(expOrNull) else read(stream, readTable);
|
return if (expOrNull != null) {
|
||||||
|
Some(expOrNull.withPos(position));
|
||||||
|
} else {
|
||||||
|
read(stream, readTable);
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -90,4 +102,11 @@ class Reader {
|
|||||||
stream.dropString(end);
|
stream.dropString(end);
|
||||||
return array;
|
return array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static function withPos(def:ReaderExpDef, pos:Position) {
|
||||||
|
return {
|
||||||
|
pos: pos,
|
||||||
|
def: def
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import haxe.macro.Context;
|
|||||||
import kiss.Reader;
|
import kiss.Reader;
|
||||||
import kiss.Types;
|
import kiss.Types;
|
||||||
|
|
||||||
|
using kiss.Reader;
|
||||||
using kiss.Helpers;
|
using kiss.Helpers;
|
||||||
using kiss.Prelude;
|
using kiss.Prelude;
|
||||||
|
|
||||||
@@ -33,7 +34,7 @@ class SpecialForms {
|
|||||||
if (args.length < 1) {
|
if (args.length < 1) {
|
||||||
throw '(new [type] constructorArgs...) is missing a type!';
|
throw '(new [type] constructorArgs...) is missing a type!';
|
||||||
}
|
}
|
||||||
var classType = switch (args[0]) {
|
var classType = switch (args[0].def) {
|
||||||
case Symbol(name): name;
|
case Symbol(name): name;
|
||||||
default: throw 'first arg in (new [type] ...) should be a class to instantiate';
|
default: throw 'first arg in (new [type] ...) should be a class to instantiate';
|
||||||
};
|
};
|
||||||
@@ -46,7 +47,7 @@ class SpecialForms {
|
|||||||
|
|
||||||
// TODO refactor out EVar generation and allow var bindings to destructure lists and key-value pairs
|
// TODO refactor out EVar generation and allow var bindings to destructure lists and key-value pairs
|
||||||
map["let"] = (args:Array<ReaderExp>, convert:ExprConversion) -> {
|
map["let"] = (args:Array<ReaderExp>, convert:ExprConversion) -> {
|
||||||
var bindingList = switch (args[0]) {
|
var bindingList = switch (args[0].def) {
|
||||||
case ListExp(bindingExps) if (bindingExps.length > 0 && bindingExps.length % 2 == 0):
|
case ListExp(bindingExps) if (bindingExps.length > 0 && bindingExps.length % 2 == 0):
|
||||||
bindingExps;
|
bindingExps;
|
||||||
default:
|
default:
|
||||||
@@ -56,13 +57,13 @@ class SpecialForms {
|
|||||||
var varDefs = [
|
var varDefs = [
|
||||||
for (bindingPair in bindingPairs)
|
for (bindingPair in bindingPairs)
|
||||||
{
|
{
|
||||||
name: switch (bindingPair[0]) {
|
name: switch (bindingPair[0].def) {
|
||||||
case Symbol(name) | TypedExp(_, Symbol(name)):
|
case Symbol(name) | TypedExp(_, {pos: _, def: Symbol(name)}):
|
||||||
name;
|
name;
|
||||||
default:
|
default:
|
||||||
throw 'first element of binding pair $bindingPair should be a symbol or typed symbol';
|
throw 'first element of binding pair $bindingPair should be a symbol or typed symbol';
|
||||||
},
|
},
|
||||||
type: switch (bindingPair[0]) {
|
type: switch (bindingPair[0].def) {
|
||||||
case TypedExp(type, _):
|
case TypedExp(type, _):
|
||||||
Helpers.parseComplexType(type);
|
Helpers.parseComplexType(type);
|
||||||
default: null;
|
default: null;
|
||||||
@@ -97,7 +98,7 @@ class SpecialForms {
|
|||||||
if (args.length != 2) {
|
if (args.length != 2) {
|
||||||
throw '(the [type] [value]) expression has wrong number of arguments: ${args.length}';
|
throw '(the [type] [value]) expression has wrong number of arguments: ${args.length}';
|
||||||
}
|
}
|
||||||
ECheckType(convert(args[1]), switch (args[0]) {
|
ECheckType(convert(args[1]), switch (args[0].def) {
|
||||||
case Symbol(type): Helpers.parseComplexType(type);
|
case Symbol(type): Helpers.parseComplexType(type);
|
||||||
default: throw 'first argument to (the... ) should be a valid type';
|
default: throw 'first argument to (the... ) should be a valid type';
|
||||||
}).withContextPos();
|
}).withContextPos();
|
||||||
@@ -111,19 +112,24 @@ class SpecialForms {
|
|||||||
var catchKissExps = args.slice(1);
|
var catchKissExps = args.slice(1);
|
||||||
ETry(convert(tryKissExp), [
|
ETry(convert(tryKissExp), [
|
||||||
for (catchKissExp in catchKissExps) {
|
for (catchKissExp in catchKissExps) {
|
||||||
switch (catchKissExp) {
|
switch (catchKissExp.def) {
|
||||||
case CallExp(Symbol("catch"), catchArgs):
|
case CallExp({pos: _, def: Symbol("catch")}, catchArgs):
|
||||||
{
|
{
|
||||||
name: switch (catchArgs[0]) {
|
name: switch (catchArgs[0].def) {
|
||||||
case ListExp([Symbol(name) | TypedExp(_, Symbol(name))]): name;
|
case ListExp([
|
||||||
|
{
|
||||||
|
pos: _,
|
||||||
|
def: Symbol(name) | TypedExp(_, {pos: _, def: Symbol(name)})
|
||||||
|
}
|
||||||
|
]): name;
|
||||||
default: throw 'first argument to (catch... ) should be a one-element argument list, not ${catchArgs[0]}';
|
default: throw 'first argument to (catch... ) should be a one-element argument list, not ${catchArgs[0]}';
|
||||||
},
|
},
|
||||||
type: switch (catchArgs[0]) {
|
type: switch (catchArgs[0].def) {
|
||||||
case ListExp([TypedExp(type, _)]):
|
case ListExp([{pos: _, def: TypedExp(type, _)}]):
|
||||||
Helpers.parseComplexType(type);
|
Helpers.parseComplexType(type);
|
||||||
default: null;
|
default: null;
|
||||||
},
|
},
|
||||||
expr: convert(CallExp(Symbol("begin"), catchArgs.slice(1)))
|
expr: convert(CallExp(Symbol("begin").withPos(catchArgs[1].pos), catchArgs.slice(1)).withPos(catchArgs[1].pos))
|
||||||
};
|
};
|
||||||
default:
|
default:
|
||||||
throw 'expressions following the first expression in a (try... ) should all be (catch... ) expressions, but you used $catchKissExp';
|
throw 'expressions following the first expression in a (try... ) should all be (catch... ) expressions, but you used $catchKissExp';
|
||||||
@@ -165,7 +171,7 @@ class SpecialForms {
|
|||||||
static function foldComparison(func:String) {
|
static function foldComparison(func:String) {
|
||||||
return (args:Array<ReaderExp>, convert:ExprConversion) -> {
|
return (args:Array<ReaderExp>, convert:ExprConversion) -> {
|
||||||
pos: Context.currentPos(),
|
pos: Context.currentPos(),
|
||||||
expr: EBinop(OpEq, convert(args[0]), convert(CallExp(Symbol(func), args)))
|
expr: EBinop(OpEq, convert(args[0]), convert(CallExp(Symbol(func).withPos(args[0].pos), args).withPos(args[0].pos)))
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import haxe.ds.Option;
|
|||||||
using StringTools;
|
using StringTools;
|
||||||
using Lambda;
|
using Lambda;
|
||||||
|
|
||||||
|
typedef Position = String;
|
||||||
|
|
||||||
class Stream {
|
class Stream {
|
||||||
var content:String;
|
var content:String;
|
||||||
var file:String;
|
var file:String;
|
||||||
@@ -34,7 +36,7 @@ class Stream {
|
|||||||
return content.length == 0;
|
return content.length == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function position() {
|
public function position():Position {
|
||||||
return '$file:$line:$column';
|
return '$file:$line:$column';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user