Refactor: SpecialForms.hx
This commit is contained in:
@@ -3,13 +3,10 @@ package kiss;
|
||||
import haxe.macro.Expr;
|
||||
import haxe.macro.Context;
|
||||
import kiss.Reader;
|
||||
import kiss.Types;
|
||||
|
||||
using StringTools;
|
||||
|
||||
// Fields usually are set to expressions, so a ReaderExp conversion function
|
||||
// needs to be passed to field forms
|
||||
typedef ExprConversion = (ReaderExp) -> Expr;
|
||||
|
||||
// Field forms convert Kiss reader expressions into Haxe macro class fields
|
||||
typedef FieldFormFunction = (position:String, args:Array<ReaderExp>, convert:ExprConversion) -> Field;
|
||||
|
||||
|
@@ -5,6 +5,7 @@ import haxe.macro.Expr;
|
||||
import kiss.Stream;
|
||||
import kiss.Reader;
|
||||
import kiss.FieldForms;
|
||||
import kiss.SpecialForms;
|
||||
|
||||
class Kiss {
|
||||
/**
|
||||
@@ -17,6 +18,7 @@ class Kiss {
|
||||
var reader = new Reader();
|
||||
|
||||
var fieldForms = FieldForms.builtins();
|
||||
var specialForms = SpecialForms.builtins();
|
||||
|
||||
while (true) {
|
||||
stream.dropWhitespace();
|
||||
@@ -30,7 +32,7 @@ class Kiss {
|
||||
// The last expression might be a comment, in which case None will be returned
|
||||
switch (nextExp) {
|
||||
case Some(nextExp):
|
||||
classFields.push(readerExpToField(nextExp, position, fieldForms));
|
||||
classFields.push(readerExpToField(nextExp, position, fieldForms, specialForms));
|
||||
case None:
|
||||
stream.dropWhitespace(); // If there was a comment, drop whitespace that comes after
|
||||
}
|
||||
@@ -39,16 +41,17 @@ class Kiss {
|
||||
return classFields;
|
||||
}
|
||||
|
||||
static function readerExpToField(exp:ReaderExp, position:String, fieldForms:Map<String, FieldFormFunction>):Field {
|
||||
static function readerExpToField(exp:ReaderExp, position:String, fieldForms:Map<String, FieldFormFunction>,
|
||||
specialForms:Map<String, SpecialFormFunction>):Field {
|
||||
return switch (exp) {
|
||||
case Call(Symbol(formName), args) if (fieldForms.exists(formName)):
|
||||
fieldForms[formName](position, args, readerExpToHaxeExpr);
|
||||
fieldForms[formName](position, args, readerExpToHaxeExpr.bind(_, specialForms));
|
||||
default:
|
||||
throw '$exp at $position is not a valid field form';
|
||||
};
|
||||
}
|
||||
|
||||
static function readerExpToHaxeExpr(exp:ReaderExp):Expr {
|
||||
static function readerExpToHaxeExpr(exp:ReaderExp, specialForms:Map<String, SpecialFormFunction>):Expr {
|
||||
var expr = switch (exp) {
|
||||
case Symbol(name):
|
||||
Context.parse(name, Context.currentPos());
|
||||
@@ -57,15 +60,12 @@ class Kiss {
|
||||
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(Symbol(specialForm), args) if (specialForms.exists(specialForm)):
|
||||
specialForms[specialForm](args, readerExpToHaxeExpr.bind(_, specialForms));
|
||||
case Call(func, body):
|
||||
{
|
||||
pos: Context.currentPos(),
|
||||
expr: ECall(readerExpToHaxeExpr(func), [for (bodyExp in body) readerExpToHaxeExpr(bodyExp)])
|
||||
expr: ECall(readerExpToHaxeExpr(func, specialForms), [for (bodyExp in body) readerExpToHaxeExpr(bodyExp, specialForms)])
|
||||
};
|
||||
case RawHaxe(code):
|
||||
Context.parse(code, Context.currentPos());
|
||||
|
22
src/kiss/SpecialForms.hx
Normal file
22
src/kiss/SpecialForms.hx
Normal file
@@ -0,0 +1,22 @@
|
||||
package kiss;
|
||||
|
||||
import haxe.macro.Expr;
|
||||
import haxe.macro.Context;
|
||||
import kiss.Reader;
|
||||
import kiss.Types;
|
||||
|
||||
// Special forms convert Kiss reader expressions into Haxe macro expressions
|
||||
typedef SpecialFormFunction = (args:Array<ReaderExp>, convert:ExprConversion) -> Expr;
|
||||
|
||||
class SpecialForms {
|
||||
public static function builtins() {
|
||||
var map:Map<String, SpecialFormFunction> = [];
|
||||
|
||||
map["begin"] = (args:Array<ReaderExp>, convert:ExprConversion) -> {
|
||||
pos: Context.currentPos(),
|
||||
expr: EBlock([for (bodyExp in args) convert(bodyExp)])
|
||||
};
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
7
src/kiss/Types.hx
Normal file
7
src/kiss/Types.hx
Normal file
@@ -0,0 +1,7 @@
|
||||
package kiss;
|
||||
|
||||
import haxe.macro.Expr;
|
||||
import kiss.Reader;
|
||||
|
||||
// A lot of special forms need to convert expressions recursively, so they get passed an ExprConversion
|
||||
typedef ExprConversion = (ReaderExp) -> Expr;
|
Reference in New Issue
Block a user