Rather than having magic conversion of command line args to numbers as
needed, introduce '$' as a prefix op to to the conversion.
This is a step towards changing 'program' to be a 'main' function.
Signed-off-by: NeilBrown <neil@brown.name>
- program A B astr bbool:
+ program As Bs astr bbool:
+ A := $As; B := $Bs
print "Hello World, what lovely oceans you have!"
/* When a variable is defined in both branches of an 'if',
* and used afterwards, the variables are merged.
print "Hello World, what lovely oceans you have!"
/* When a variable is defined in both branches of an 'if',
* and used afterwards, the variables are merged.
### Expressions: The rest
### Expressions: The rest
-The remaining expressions with the highest precedence are arithmetic and
-string concatenation. String concatenation (`++`) has the same
-precedence as multiplication and division, but lower than the uniary.
+The remaining expressions with the highest precedence are arithmetic,
+string concatenation, and string conversion. String concatenation
+(`++`) has the same precedence as multiplication and division, but lower
+than the uniary.
+
+String conversion is a temporary feature until I get a better type
+system. `$` is a prefix operator which expects a string and returns
+a number.
`+` and `-` are both infix and prefix operations (where they are
absolute value and negation). These have different operator names.
`+` and `-` are both infix and prefix operations (where they are
absolute value and negation). These have different operator names.
Times, Divide, Rem,
Concat,
Absolute, Negate,
Times, Divide, Rem,
Concat,
Absolute, Negate,
Bracket,
###### expr precedence
$LEFT + - Eop
$LEFT * / % ++ Top
Bracket,
###### expr precedence
$LEFT + - Eop
$LEFT * / % ++ Top
$TERM ( )
###### expression grammar
$TERM ( )
###### expression grammar
Uop -> + ${ $0.op = Absolute; }$
| - ${ $0.op = Negate; }$
Uop -> + ${ $0.op = Absolute; }$
| - ${ $0.op = Negate; }$
+ | $ ${ $0.op = StringConv; }$
Top -> * ${ $0.op = Times; }$
| / ${ $0.op = Divide; }$
Top -> * ${ $0.op = Times; }$
| / ${ $0.op = Divide; }$
if (bracket) printf(")");
break;
case Absolute:
if (bracket) printf(")");
break;
case Absolute:
- if (bracket) printf("(");
- printf("+");
- print_exec(b->right, indent, bracket);
- if (bracket) printf(")");
- break;
if (bracket) printf("(");
if (bracket) printf("(");
+ switch (b->op) {
+ case Absolute: fputs("+", stdout); break;
+ case Negate: fputs("-", stdout); break;
+ case StringConv: fputs("$", stdout); break;
+ default: abort(); // NOTEST
+ } // NOTEST
print_exec(b->right, indent, bracket);
if (bracket) printf(")");
break;
print_exec(b->right, indent, bracket);
if (bracket) printf(")");
break;
Tstr, rules, type);
return Tstr;
Tstr, rules, type);
return Tstr;
+ case StringConv:
+ /* op must be string, result is number */
+ propagate_types(b->left, c, ok, Tstr, 0);
+ if (!type_compat(type, Tnum, 0))
+ type_err(c,
+ "error: Can only convert string to number, not %1",
+ prog, type, 0, NULL);
+ return Tnum;
+
case Bracket:
return propagate_types(b->right, c, ok, type, 0);
case Bracket:
return propagate_types(b->right, c, ok, type, 0);
rvtype = Tstr;
rv.str = text_join(left.str, right.str);
break;
rvtype = Tstr;
rv.str = text_join(left.str, right.str);
break;
+ case StringConv:
+ right = interp_exec(b->right, &rvtype);
+ rtype = Tstr;
+ rvtype = Tnum;
+ char *str = strndup(right.str.txt, right.str.len);
+ parse_value(rvtype, str, &rv);
+ free(str);
+ break;
name:string
alive:Boolean
name:string
alive:Boolean
print "Hello World, what lovely oceans you have!"
print "Are there", five, "?"
print pi, pie, "but", cake
print "Hello World, what lovely oceans you have!"
print "Are there", five, "?"
print pi, pie, "but", cake
+ A := $Astr; B := $Bstr
+
/* When a variable is defined in both branches of an 'if',
* and used afterwards, the variables are merged.
*/
/* When a variable is defined in both branches of an 'if',
* and used afterwards, the variables are merged.
*/