updated code sample in the readme

This commit is contained in:
cozis
2022-08-15 04:16:30 +02:00
parent 6bd60bc84a
commit 8cac46440b
3 changed files with 47 additions and 28 deletions
+15 -11
View File
@@ -21,25 +21,29 @@ Here's an example of a noja program that orders the items in list using a bubble
``` ```
L = [3, 2, 1]; L = [3, 2, 1];
do { fun swap(a: int, b: int)
return b, a;
fun order(L: List) {
do {
swapped = false; swapped = false;
i = 0; i = 0;
while i < count(L)-1 and not swapped: { while i < count(L)-1 and not swapped: {
if L[i+1] < L[i]: { swapped = L[i+1] < L[i];
if swapped:
L[i], L[i+1] = swap(L[i], L[i+1]);
swapped = true; i = i+1;
tmp = L[i+1];
L[i+1] = L[i];
L[i] = tmp;
} }
} while swapped;
}
i = i + 1; print(L, '\n'); # [3, 2, 1]
} order(L);
} while swapped; print(L, '\n'); # [1, 2, 3]
print(L, '\n'); # Outputs [1, 2, 3]
``` ```
## Implementation Overview ## Implementation Overview
+15 -12
View File
@@ -1,21 +1,21 @@
fun isSpace(c) fun isSpace(c: String)
return c == " " or c == "\t" or c == "\n"; return c == " " or c == "\t" or c == "\n";
fun isDigit(c) { fun isDigit(c: String) {
u = unicode(c); u = unicode(c);
d = u - unicode("0"); d = u - unicode("0");
return d >= 0 and d <= 9; return d >= 0 and d <= 9;
} }
fun skipSpaces(context) { fun skipSpaces(context: Map) {
# Skip zero or more whitespace characters. # Skip zero or more whitespace characters.
while context.cur < count(context.str) while context.cur < count(context.str)
and isSpace(context.str[context.cur]): and isSpace(context.str[context.cur]):
context.cur = context.cur + 1; context.cur = context.cur + 1;
} }
fun parseNull(context) { fun parseNull(context: Map) {
assert(context.cur < count(context) assert(context.cur < count(context)
and context.str[context.cur] == 'n'); and context.str[context.cur] == 'n');
@@ -30,7 +30,7 @@ fun parseNull(context) {
return none; return none;
} }
fun parseTrue(context) { fun parseTrue(context: Map) {
assert(context.cur < count(context) assert(context.cur < count(context)
and context.str[context.cur] == 't'); and context.str[context.cur] == 't');
@@ -45,7 +45,7 @@ fun parseTrue(context) {
return true; return true;
} }
fun parseFalse(context) { fun parseFalse(context: Map) {
assert(context.cur < count(context) assert(context.cur < count(context)
and context.str[context.cur] == 'f'); and context.str[context.cur] == 'f');
@@ -61,14 +61,17 @@ fun parseFalse(context) {
return false; return false;
} }
fun skip(context, test_callback) { fun dummy() {}
Func = type(dummy);
fun skip(context: Map, test_callback: Func) {
k = context.cur; k = context.cur;
while k < count(context) and test_callback(context.str[k]): while k < count(context) and test_callback(context.str[k]):
k = k + 1; k = k + 1;
return k; return k;
} }
fun parseInteger(context) { fun parseInteger(context: Map) {
assert(context.cur < count(context) and isDigit(context.str[context.cur])); assert(context.cur < count(context) and isDigit(context.str[context.cur]));
buffer = 0; buffer = 0;
@@ -84,7 +87,7 @@ fun parseInteger(context) {
return buffer; return buffer;
} }
fun parseFloating(context) { fun parseFloating(context: Map) {
assert(context.cur < count(context) and isDigit(context.str[context.cur])); assert(context.cur < count(context) and isDigit(context.str[context.cur]));
# It's ensured by the caller (parseIntegerOrFloating) # It's ensured by the caller (parseIntegerOrFloating)
@@ -117,7 +120,7 @@ fun parseFloating(context) {
return buffer; return buffer;
} }
fun parseIntegerOrFloating(context) { fun parseIntegerOrFloating(context: Map) {
assert(context.cur < count(context) and isDigit(context.str[context.cur])); assert(context.cur < count(context) and isDigit(context.str[context.cur]));
# Is the first digit sequence followed by a dot # Is the first digit sequence followed by a dot
@@ -132,7 +135,7 @@ fun parseIntegerOrFloating(context) {
return parseInteger(context); return parseInteger(context);
} }
fun parseValue(context) { fun parseValue(context: Map) {
if context.cur == count(context): if context.cur == count(context):
return none, "Source ended where a value was expected"; return none, "Source ended where a value was expected";
@@ -159,7 +162,7 @@ fun parseValue(context) {
return val, err; return val, err;
} }
fun parse(str) { fun parse(str: String) {
context = {str: str, cur: 0}; context = {str: str, cur: 0};
skipSpaces(context); skipSpaces(context);
val, err = parseValue(context); val, err = parseValue(context);
+13 -1
View File
@@ -208,15 +208,24 @@ static void emitInstrForFuncCallNode(CodegenContext *ctx, CallExprNode *expr,
static void emitInstrForArgumentNode(CodegenContext *ctx, ArgumentNode *arg, int argidx) static void emitInstrForArgumentNode(CodegenContext *ctx, ArgumentNode *arg, int argidx)
{ {
/* /*
* // Push the type of the argument
* PUSHTYP; * PUSHTYP;
* <arg-type-0> // What if this isn't a type? *
* // Evaluate the type annotation and make
* // sure that it evaluated to a type.
* <arg-type-0>
* PUSHTYP; * PUSHTYP;
* PUSHTYPTYP; * PUSHTYPTYP;
* EQL; * EQL;
* JUMPIFANDPOP argument_annotation_0_not_type; * JUMPIFANDPOP argument_annotation_0_not_type;
*
* // If the annotated type and the argument's
* // type match, jump to the argument assignment.
* EQL; * EQL;
* JUMPIFANDPOP argument_type_ok; * JUMPIFANDPOP argument_type_ok;
* *
* // To the same for the next annotation.
*
* PUSHTYP; * PUSHTYP;
* <arg-type-1> * <arg-type-1>
* PUSHTYP; * PUSHTYP;
@@ -239,6 +248,9 @@ static void emitInstrForArgumentNode(CodegenContext *ctx, ArgumentNode *arg, int
* argument_annotation_0_not_a_type: * argument_annotation_0_not_a_type:
* ERROR "Argument N annotation M isn't a type"; * ERROR "Argument N annotation M isn't a type";
* argument_type_ok: * argument_type_ok:
*
* // At this point we know that the argument has
* // a valid type.
* ASS <arg-name>; * ASS <arg-name>;
* POP 1; * POP 1;
*/ */