diff --git a/docs/index.html b/docs/index.html index 89239c1..958cef4 100644 --- a/docs/index.html +++ b/docs/index.html @@ -43,7 +43,10 @@ - + + + +

🐝 Wasp

diff --git a/source/Angle.cpp b/source/Angle.cpp index e1420f4..5819c52 100644 --- a/source/Angle.cpp +++ b/source/Angle.cpp @@ -741,6 +741,9 @@ Node &groupTypes(Node &expression, Function &context) { expression.remove(i, i);// move type to type field of instance Node *typed = 0; + if (is_operator(expression.children[i].name[0])) { + i++; + } if (i < expression.length and not is_operator(expression.children[i].name[0])) { typed = &expression.children[i]; } else if (i > 1) { // special reverse syntax a int, jeff as int @@ -823,9 +826,11 @@ void updateLocal(Function &context, String name, Type type) { local.type = genericType(array, type); } } else { - if (!compatibleTypes(oldType, type)) - warn("local "s + name + " in context %s already known "s % context.name + " with type " + + if (!compatibleTypes(oldType, type)) { +// warn + error("local "s + name + " in context %s already known "s % context.name + " with type " + typeName(oldType) + ", ignoring new type " + type_name); + } } } // ok, could be cast'able! @@ -834,6 +839,7 @@ void updateLocal(Function &context, String name, Type type) { bool compatibleTypes(Type type1, Type type2) { if (type1 == type2)return true; if (type1 == string_struct and type2 == strings)return true; + if (type1 == wasm_int32 and type2 == wasm_int64)return true; // upcast return false; } diff --git a/source/DwarfEmitter.cpp b/source/DwarfEmitter.cpp index e6d6264..2d55faf 100644 --- a/source/DwarfEmitter.cpp +++ b/source/DwarfEmitter.cpp @@ -934,7 +934,7 @@ void testSourceMapHardCoded() { void testSourceMap() { // testSourceMapHardCoded(); - assert_emit("int tttt(int j){x=j+1;x};tttt(3)", 4); +// assert_emit("int tttt(int j){x=j+1;x};tttt(3)", 4); } diff --git a/source/Wasp.cpp b/source/Wasp.cpp index d6bc50d..6b85992 100644 --- a/source/Wasp.cpp +++ b/source/Wasp.cpp @@ -728,12 +728,28 @@ class Wasp { return String((char) (uffff));// itoa0(uffff); } - Node string(codepoint delim = '"') { + void parserError(String message) { + String msg = message; + msg += position(); + auto error = new SyntaxError(msg); + error->at = at; + error->lineNumber = lineNumber; + error->columnNumber = at - columnStart; + error->file = file.data; + err(msg); + } + + bool end_of_text() { + return at >= text.length; + } + + Node quote(codepoint delim = '"') { proceed(); int start = at; while (ch and ch != delim and previous != '\\') proceed(); -// const String &substring = text.substring(start, at - 1); + if (end_of_text()) + parserError("Unterminated string"); String substring = text.substring(start, at); proceed(); return Node(substring).setType(strings);// DONT do "3"==3 (here or ever)! @@ -1679,9 +1695,9 @@ class Wasp { matches = matches or (close == u'”' and ch == u'“'); if (!matches) { // open string if (actual.last().kind == expression) - actual.last().addSmart(string(closer)); + actual.last().addSmart(quote(closer)); else - actual.add(string(closer).clone()); + actual.add(quote(closer).clone()); break; } Node id = Node(text.substring(start, at)); diff --git a/source/asserts.h b/source/asserts.h index 7537184..24804ea 100644 --- a/source/asserts.h +++ b/source/asserts.h @@ -88,7 +88,7 @@ static List done; #define assert_emit(α, β) printf("%s\n%s:%d\n",α,__FILE__,__LINE__);if (!assert_equals_x(eval(α),β)){printf("%s != %s",#α,#β);backtrace_line();} #endif //#define assert_emit(α, β) try{printf("%s\n%s:%d\n",α,__FILE__,__LINE__);if (!assert_equals_x(emit(α),β)){printf("%s != %s",#α,#β);backtrace_line();}}catch(chars x){printf("%s\nIN %s",x,α);backtrace_line();} - +#define check_emit assert_emit #if RUNTIME_ONLY or MY_WASM #define assert_run(a, b) skip(a) // use assert_emit if runtime is not needed!! much easier to debug diff --git a/source/tests.cpp b/source/tests.cpp index 0577ebf..6854a98 100644 --- a/source/tests.cpp +++ b/source/tests.cpp @@ -25,6 +25,19 @@ //void testDwarf(); //void testSourceMap(); +void testExceptions() { + assert_throws("x:int=1;x='ok'"); + assert_throws("x:int=1;x=1.1"); +// assert_emit("x:int=1;x=1.0",1); // might be cast by compiler +// assert_emit("x=1;x='ok';x=1", 1); // untyped x can be reassigned + assert_throws("'unclosed quote"); + assert_throws("\"unclosed quote"); + assert_throws("unclosed quote'"); + assert_throws("unclosed quote\""); + assert_throws("unclosed bracket)"); + assert_throws("(unclosed bracket"); +} + void testNoBlock() { // fixed assert_parses(R"( #see math.wasp ! @@ -1804,7 +1817,11 @@ void testMathExtra() { assert_is("15÷5", 3); assert_emit("15÷5", 3); assert_emit("3⋅5", 15); - assert_emit("3×5", 15); + assert_emit("3×5", 15); + assert_emit("3^3", 27); + assert_emit("3**3", 27); + assert_emit("√3**2", 3); + assert_emit("√3^2", 3); assert_is("one plus two times three", 7); } @@ -3386,7 +3403,9 @@ void pleaseFix() { // 2022-12-28 : 3 sec WITH runtime_emit, wasmedge on M1 WOW ALL TESTS PASSING // ⚠️ CANNOT USE assert_emit in WASM! ONLY via void testRun(); void testCurrent() { - +// check_is("τ≈6.2831853",true); +// assert_emit("τ≈6.2831853",1); + testExceptions(); // assert_emit("√ π ²", pi); // assert_emit("√π²", pi); diff --git a/source/wasm_emitter.cpp b/source/wasm_emitter.cpp index cab175b..29b1757 100644 --- a/source/wasm_emitter.cpp +++ b/source/wasm_emitter.cpp @@ -219,6 +219,8 @@ unsigned short opcodes(chars s, Valtype kind, Valtype previous = none) { if (eq(s, "*"))return f64_mul; // f64.mul if (eq(s, "/"))return f64_div; // f64.div if (eq(s, "=="))return f64_eq; // f64.eq + if (eq(s, "~"))return f64_eq; // f32.eq Todo + if (eq(s, "≈"))return f64_eq; // f32.eq Todo if (eq(s, ">"))return f64_gt; // f64.gt if (eq(s, ">="))return f64_ge; // f64.ge if (eq(s, "<"))return f64_lt; // f64.lt @@ -248,12 +250,14 @@ unsigned short opcodes(chars s, Valtype kind, Valtype previous = none) { if (eq(s, "not"))return f32_eqz; // f32.eqz // f32.eqz // HACK: no such thing! if (eq(s, "¬"))return f32_eqz; // f32.eqz // HACK: no such thing! if (eq(s, "!"))return f32_eqz; // f32.eqz // HACK: no such thing! - if (eq(s, "+"))return f32_add; // f32.add if (eq(s, "-"))return f32_sub; // f32.sub if (eq(s, "*"))return f32_mul; // f32.mul if (eq(s, "/"))return f32_div; // f32.div + if (eq(s, "="))return f32_eq; // f32.eq if (eq(s, "=="))return f32_eq; // f32.eq + if (eq(s, "~"))return f32_eq; // f32.eq Todo + if (eq(s, "≈"))return f32_eq; // f32.eq Todo if (eq(s, ">"))return f32_gt; // f32.gt if (eq(s, ">="))return f32_ge; // f32.ge if (eq(s, "<"))return f32_lt; // f32.lt @@ -319,6 +323,7 @@ enum ExportType { // todo == ExternalKind global_export = 0x03 }; + // http://webassembly.github.io/spec/core/binary/types.html#context-types char functionType = 0x60; @@ -375,6 +380,14 @@ bool isProperList(Node &node) { return true; } +Code emitSimilar(Node &node, Function &context) { + Code code; + // a ≈ b <> | a - b | < ε +// code.add(emitCall(*new Node("similar"), context)); + todow("emitSimilar a ≈ b <> | a - b | < ε e.g. π≈3.14159"); + return code; +} + // append padding bytes to wasm data memory void emitPadding(int num, byte val = 0) { while (num-- > 0) @@ -1768,6 +1781,8 @@ Code emitOperator(Node &node, Function &context) { return code.add(emitCall(Node("modulo_double").setType(call), context));// mod_d } else if (name == "?") { return emitIf(node, context); + } else if (name == "≈") { + return emitSimilar(node, context); } else if (name == "ⁿ") { if (node.length == 1) { code.add(cast(last_type, float64));// todo all casts should be auto-cast (in emitCall) now, right?