Refactor: SpecialForms.hx

This commit is contained in:
2020-11-13 15:28:49 -07:00
parent bc37381a47
commit 014893271e
4 changed files with 40 additions and 14 deletions

View File

@@ -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;

View File

@@ -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
View 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
View 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;