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 @@
-
+
+
+
+
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?