Allow type hints on functions and vars
This commit is contained in:
@@ -4,6 +4,7 @@ import haxe.macro.Expr;
|
||||
import haxe.macro.Context;
|
||||
import kiss.Reader;
|
||||
import kiss.Types;
|
||||
import kiss.Helpers;
|
||||
|
||||
using StringTools;
|
||||
|
||||
@@ -34,10 +35,10 @@ class FieldForms {
|
||||
|
||||
static function fieldName(formName:String, position:String, nameExp:ReaderExp) {
|
||||
return switch (nameExp) {
|
||||
case Symbol(name):
|
||||
case Symbol(name) | TypedExp(_, Symbol(name)):
|
||||
name;
|
||||
default:
|
||||
throw 'The first argument to $formName at $position should be a variable name';
|
||||
throw 'The first argument to $formName at $position should be a variable name or typed variable name';
|
||||
};
|
||||
}
|
||||
|
||||
@@ -52,8 +53,11 @@ class FieldForms {
|
||||
return {
|
||||
name: name,
|
||||
access: access,
|
||||
kind: FVar(null, // TODO allow type anotations
|
||||
convert(args[1])),
|
||||
kind: FVar(switch (args[0]) {
|
||||
case TypedExp(type, _):
|
||||
Helpers.parseTypePath(type);
|
||||
default: null;
|
||||
}, convert(args[1])),
|
||||
pos: Context.currentPos()
|
||||
};
|
||||
}
|
||||
@@ -70,10 +74,12 @@ class FieldForms {
|
||||
return {
|
||||
name: name,
|
||||
access: access,
|
||||
// TODO type parameter declarations
|
||||
kind: FFun({
|
||||
args: switch (args[1]) {
|
||||
case ListExp(funcArgs):
|
||||
[
|
||||
// TODO optional arguments, default values
|
||||
for (funcArg in funcArgs)
|
||||
{
|
||||
name: switch (funcArg) {
|
||||
@@ -82,7 +88,11 @@ class FieldForms {
|
||||
default:
|
||||
throw '$funcArg should be a symbol or typed symbol for a function argument';
|
||||
},
|
||||
type: null
|
||||
type: switch (funcArg) {
|
||||
case TypedExp(type, _):
|
||||
Helpers.parseTypePath(type);
|
||||
default: null;
|
||||
}
|
||||
}
|
||||
];
|
||||
case CallExp(_, _):
|
||||
@@ -90,7 +100,10 @@ class FieldForms {
|
||||
default:
|
||||
throw '${args[1]} should be an argument list';
|
||||
},
|
||||
ret: null,
|
||||
ret: switch (args[0]) {
|
||||
case TypedExp(type, _): Helpers.parseTypePath(type);
|
||||
default: null;
|
||||
},
|
||||
expr: {
|
||||
pos: Context.currentPos(),
|
||||
expr: EReturn(convert(CallExp(Symbol("begin"), args.slice(2))))
|
||||
|
@@ -3,6 +3,8 @@ package kiss;
|
||||
import haxe.macro.Expr;
|
||||
import haxe.macro.Context;
|
||||
|
||||
using StringTools;
|
||||
|
||||
class Helpers {
|
||||
public static function withPos(e:ExprDef):Expr {
|
||||
return {
|
||||
@@ -10,4 +12,35 @@ class Helpers {
|
||||
expr: e
|
||||
};
|
||||
}
|
||||
|
||||
static function startsWithUpperCase(s:String) {
|
||||
return s.charAt(0) == s.charAt(0).toUpperCase();
|
||||
}
|
||||
|
||||
// TODO this doesn't parse generic typeparams yet
|
||||
public static function parseTypePath(path:String):ComplexType {
|
||||
var parts:List<String> = path.split(".");
|
||||
var uppercaseParts:List<Bool> = parts.map(startsWithUpperCase);
|
||||
for (isUpcase in uppercaseParts.slice(0, -2)) {
|
||||
if (isUpcase) {
|
||||
throw 'Type path $path should only have capitalized type and subtype';
|
||||
}
|
||||
}
|
||||
var lastIsCap = uppercaseParts[-1];
|
||||
var penultIsCap = uppercaseParts[-2];
|
||||
return TPath(if (lastIsCap && penultIsCap) {
|
||||
{
|
||||
sub: parts[-1],
|
||||
name: parts[-2],
|
||||
pack: parts.slice(0, -2)
|
||||
};
|
||||
} else if (lastIsCap) {
|
||||
{
|
||||
name: parts[-1],
|
||||
pack: parts.slice(0, -1)
|
||||
};
|
||||
} else {
|
||||
throw 'Type path $path should end with a capitalized type';
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@@ -127,4 +127,8 @@ class BasicTestCase extends Test {
|
||||
seasonsGreetings += "ho ";
|
||||
}));
|
||||
}
|
||||
|
||||
function testTypedDefvar() {
|
||||
Assert.equals(8, BasicTestCase.myInt);
|
||||
}
|
||||
}
|
||||
|
@@ -63,12 +63,14 @@
|
||||
(defvar myIf7 (if "string" true false))
|
||||
(defvar myIf8 (if "" true false))
|
||||
|
||||
(defvar :Int myInt 8)
|
||||
|
||||
(defmacrofun doTwiceInt [intOp]
|
||||
,intOp
|
||||
,intOp)
|
||||
|
||||
// I think this causes doTwiceInt's runtime function to be typed as requiring Quote<Int> and returning Int
|
||||
(defun incrementTwice [:Int val]
|
||||
(defun :Int incrementTwice [:Int val]
|
||||
(doTwiceInt ++val))
|
||||
|
||||
(defmacrofun doTwiceString [stringOp]
|
||||
|
Reference in New Issue
Block a user