defun
This commit is contained in:
@@ -14,7 +14,10 @@ class Hiss {
|
||||
|
||||
var stream = new Stream(hissFile);
|
||||
var reader = new Reader();
|
||||
while (!stream.isEmpty()) {
|
||||
while (true) {
|
||||
stream.dropWhitespace();
|
||||
if (stream.isEmpty())
|
||||
break;
|
||||
var position = stream.position();
|
||||
var nextExp = reader.read(stream);
|
||||
trace(nextExp);
|
||||
@@ -23,6 +26,7 @@ class Hiss {
|
||||
case Some(nextExp):
|
||||
classFields.push(readerExpToField(nextExp, position));
|
||||
case None:
|
||||
stream.dropWhitespace(); // If there was a comment, drop whitespace that comes after
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,9 +34,9 @@ class Hiss {
|
||||
}
|
||||
|
||||
static function readerExpToField(exp:ReaderExp, position:String):Field {
|
||||
switch (exp) {
|
||||
return switch (exp) {
|
||||
case Call(Symbol("defvar"), args) if (args.length == 2):
|
||||
return {
|
||||
{
|
||||
name: switch (args[0]) {
|
||||
case Symbol(name):
|
||||
name;
|
||||
@@ -44,22 +48,71 @@ class Hiss {
|
||||
readerExpToHaxeExpr(args[1])),
|
||||
pos: Context.currentPos()
|
||||
};
|
||||
case Call(Symbol("defun"), args) if (args.length > 2):
|
||||
{
|
||||
name: switch (args[0]) {
|
||||
case Symbol(name):
|
||||
name;
|
||||
default:
|
||||
throw 'The first argument to defun at $position should be a function name';
|
||||
},
|
||||
access: [APublic, AStatic],
|
||||
kind: FFun({
|
||||
args: switch (args[1]) {
|
||||
case List(funcArgs):
|
||||
[
|
||||
for (funcArg in funcArgs)
|
||||
{
|
||||
name: switch (funcArg) {
|
||||
case Symbol(name):
|
||||
name;
|
||||
default:
|
||||
throw '$funcArg should be a symbol for a function argument';
|
||||
},
|
||||
type: null
|
||||
}
|
||||
];
|
||||
default:
|
||||
throw '$args[1] should be an argument list';
|
||||
},
|
||||
ret: null,
|
||||
expr: {
|
||||
pos: Context.currentPos(),
|
||||
expr: EReturn(readerExpToHaxeExpr(Call(Symbol("begin"), args.slice(2))))
|
||||
}
|
||||
}),
|
||||
pos: Context.currentPos()
|
||||
};
|
||||
default:
|
||||
throw '$exp at $position is not a valid defvar or defun expression';
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
static function readerExpToHaxeExpr(exp:ReaderExp):Expr {
|
||||
return switch (exp) {
|
||||
var expr = switch (exp) {
|
||||
case Symbol(name):
|
||||
Context.parse(name, Context.currentPos());
|
||||
case Str(s):
|
||||
return {
|
||||
{
|
||||
pos: Context.currentPos(),
|
||||
expr: EConst(CString(s))
|
||||
};
|
||||
case Call(Symbol("begin"), body):
|
||||
{
|
||||
pos: Context.currentPos(),
|
||||
expr: EBlock([for (bodyExp in body) readerExpToHaxeExpr(bodyExp)])
|
||||
};
|
||||
case Call(func, body):
|
||||
{
|
||||
pos: Context.currentPos(),
|
||||
expr: ECall(readerExpToHaxeExpr(func), [for (bodyExp in body) readerExpToHaxeExpr(bodyExp)])
|
||||
};
|
||||
case RawHaxe(code):
|
||||
Context.parse(code, Context.currentPos());
|
||||
default:
|
||||
throw 'cannot convert $exp yet';
|
||||
};
|
||||
trace(expr.expr);
|
||||
return expr;
|
||||
}
|
||||
}
|
||||
|
@@ -1 +1,6 @@
|
||||
(defvar message "Hello, world!")
|
||||
(defvar message "Hello, world!")
|
||||
(defvar math #|5 + 6 * 3|#) // inject raw haxe
|
||||
(defun floor [num] (Math.floor num))
|
||||
(defun main []
|
||||
(trace message)
|
||||
(trace (floor 7.5)))
|
@@ -1,8 +1,4 @@
|
||||
package hiss;
|
||||
|
||||
@:build(hiss.Hiss.build("src/hiss/Main.hiss"))
|
||||
class Main {
|
||||
public static function main() {
|
||||
trace(message);
|
||||
}
|
||||
}
|
||||
class Main {}
|
||||
|
@@ -6,8 +6,9 @@ import hiss.Stream;
|
||||
enum ReaderExp {
|
||||
Call(func:ReaderExp, args:Array<ReaderExp>); // (f a1 a2...)
|
||||
List(exps:Array<ReaderExp>); // [v1 v2 v3]
|
||||
Str(s:String);
|
||||
Str(s:String); // "literal"
|
||||
Symbol(name:String); // s
|
||||
RawHaxe(code:String);
|
||||
}
|
||||
|
||||
typedef ReadFunction = (Stream) -> Null<ReaderExp>;
|
||||
@@ -21,12 +22,14 @@ class Reader {
|
||||
readTable["\""] = (stream) -> Str(stream.expect("closing \"", () -> stream.takeUntilAndDrop("\"")));
|
||||
readTable["/*"] = (stream) -> {
|
||||
stream.dropUntil("*/");
|
||||
stream.dropString("*/");
|
||||
null;
|
||||
};
|
||||
readTable["//"] = (stream) -> {
|
||||
stream.dropUntil("\n");
|
||||
null;
|
||||
};
|
||||
readTable["#|"] = (stream) -> RawHaxe(stream.expect("closing |", () -> stream.takeUntilAndDrop("|#")));
|
||||
}
|
||||
|
||||
public function assertRead(stream:Stream):ReaderExp {
|
||||
@@ -40,6 +43,8 @@ class Reader {
|
||||
}
|
||||
|
||||
public function read(stream:Stream):Option<ReaderExp> {
|
||||
stream.dropWhitespace();
|
||||
|
||||
var readTableKeys = [for (key in readTable.keys()) key];
|
||||
readTableKeys.sort((a, b) -> b.length - a.length);
|
||||
|
||||
|
@@ -15,6 +15,9 @@ class Stream {
|
||||
public function new(file:String) {
|
||||
// Banish ye Windows line-endings
|
||||
content = File.getContent(file).replace('\r', '');
|
||||
// Life is easier with a trailing newline
|
||||
if (content.charAt(content.length - 1) != "\n")
|
||||
content += "\n";
|
||||
|
||||
this.file = file;
|
||||
line = 1;
|
||||
|
Reference in New Issue
Block a user