Standardized CompileError

This commit is contained in:
2020-11-25 12:48:33 -07:00
parent 2bd7d32f48
commit ef17151f86
4 changed files with 84 additions and 34 deletions

View File

@@ -22,6 +22,7 @@ Kiss is a work in progress. (See: [Who should use Kiss?](#who-should-use-kiss))
- [ ] [Reader macros](https://gist.github.com/chaitanyagupta/9324402)
- [ ] Plug-and-play with every pure-Haxe library on Haxelib
- [ ] Smooth FFI with any non-Haxe library you can find or write Haxe bindings for
- [ ] helpful compiler errors
**Extra goodies:**

41
src/kiss/CompileError.hx Normal file
View File

@@ -0,0 +1,41 @@
package kiss;
import kiss.Reader;
import kiss.List;
using kiss.Reader;
class CompileError {
var exps:List<ReaderExp>;
var message:String;
function new(exps:Array<ReaderExp>, message:String) {
this.exps = exps;
this.message = message;
}
public static function fromExp(exp:ReaderExp, message:String) {
return new CompileError([exp], message);
}
public static function fromArgs(exps:Array<ReaderExp>, message:String) {
return new CompileError(exps, message);
}
public function toString() {
var posPrefix = switch (exps.length) {
case 1:
exps[0].pos;
default:
var justLineAndColumnIdx = exps[-1].pos.indexOf(":") + 1;
exps[0].pos + '-' + exps[-1].pos.substr(justLineAndColumnIdx);
}
return '\nKiss compilation failed!\n'
+ posPrefix
+ ": "
+ message
+ "\nFrom:"
+ [for (exp in exps) exp.def.toString()].toString();
}
}

View File

@@ -6,6 +6,7 @@ import kiss.Reader;
import kiss.Types;
import kiss.Helpers;
import kiss.Stream;
import kiss.CompileError;
using kiss.Reader;
using StringTools;
@@ -40,13 +41,13 @@ class FieldForms {
case Symbol(name) | TypedExp(_, {pos: _, def: Symbol(name)}):
name;
default:
throw 'The first argument to $formName at ${nameExp.pos} should be a variable name or typed variable name';
throw CompileError.fromExp(nameExp, 'The first argument to $formName should be a variable name or typed variable name.');
};
}
static function varOrProperty(formName:String, position:Position, args:Array<ReaderExp>, convert:ExprConversion):Field {
if (args.length < 2 || args.length > 3) {
throw '$formName with $args at $position has wrong number of arguments';
throw CompileError.fromArgs(args, '$formName has wrong number of arguments');
}
var name = fieldName(formName, args[0]);

View File

@@ -9,6 +9,7 @@ import kiss.FieldForms;
import kiss.SpecialForms;
import kiss.Macros;
import kiss.Types;
import kiss.CompileError;
typedef KissState = {
className:String,
@@ -24,42 +25,48 @@ class Kiss {
Build a Haxe class from a corresponding .kiss file
**/
macro static public function build(kissFile:String):Array<Field> {
var classFields = Context.getBuildFields();
var className = Context.getLocalClass().get().name;
try {
var classFields = Context.getBuildFields();
var className = Context.getLocalClass().get().name;
var stream = new Stream(kissFile);
var stream = new Stream(kissFile);
var k = {
className: className,
readTable: Reader.builtins(),
fieldForms: FieldForms.builtins(),
specialForms: SpecialForms.builtins(),
macros: Macros.builtins(),
convert: null
}
k.convert = readerExpToHaxeExpr.bind(_, k);
while (true) {
stream.dropWhitespace();
if (stream.isEmpty())
break;
var position = stream.position();
var nextExp = Reader.read(stream, k.readTable);
#if test
trace(nextExp);
#end
// The last expression might be a comment, in which case None will be returned
switch (nextExp) {
case Some(nextExp):
var field = readerExpToField(nextExp, position, k);
if (field != null)
classFields.push(field);
case None:
stream.dropWhitespace(); // If there was a comment, drop whitespace that comes after
var k = {
className: className,
readTable: Reader.builtins(),
fieldForms: FieldForms.builtins(),
specialForms: SpecialForms.builtins(),
macros: Macros.builtins(),
convert: null
}
}
k.convert = readerExpToHaxeExpr.bind(_, k);
return classFields;
while (true) {
stream.dropWhitespace();
if (stream.isEmpty())
break;
var position = stream.position();
var nextExp = Reader.read(stream, k.readTable);
#if test
trace(nextExp);
#end
// The last expression might be a comment, in which case None will be returned
switch (nextExp) {
case Some(nextExp):
var field = readerExpToField(nextExp, position, k);
if (field != null)
classFields.push(field);
case None:
stream.dropWhitespace(); // If there was a comment, drop whitespace that comes after
}
}
return classFields;
} catch (err:CompileError) {
Sys.println(err);
Sys.exit(1);
return null; // Necessary for build() to compile
}
}
static function readerExpToField(exp:ReaderExp, position:Position, k:KissState):Null<Field> {