diff --git a/README.md b/README.md
index 740163d..e151aff 100644
--- a/README.md
+++ b/README.md
@@ -761,6 +761,8 @@ If get this, Congratulations!
Must use `var` to define variables
This interpreter uses more strict syntax to make sure it is easier for you to program and debug.
+And flightgear's nasal interpreter also has the same rule.
+So do not use varibale without using `var` to declare it.
In Andy's interpreter:
@@ -794,32 +796,6 @@ code: undefined symbol "i"
-Default dynamic arguments not supported
-
-In this interpreter,
-function doesn't put dynamic args into vector `arg` by default.
-So if you use `arg` without definition,
-you'll get an error of `undefined symbol`.
-
-```javascript
-var f=func(){
- println(arg)
-}
-f(1,2,3);
-```
-
-Compilation result:
-
-```javascript
-code: undefined symbol "arg"
- --> test.nas:2:15
- |
-2 | println(arg)
- | ^ undefined symbol "arg"
-```
-
-
-
## __Trace Back Info__

diff --git a/doc/README_zh.md b/doc/README_zh.md
index a721005..90ee530 100644
--- a/doc/README_zh.md
+++ b/doc/README_zh.md
@@ -735,6 +735,7 @@ dylib.dlclose(dlhandle.lib);
必须用 var 定义变量
这个解释器使用了更加严格的语法检查来保证你可以更轻松地debug。这是非常有必要的严格,否则debug会非常痛苦。
+同样的,flightgear 内置的 nasal 解释器也采取了类似的措施,所以使用变量前务必用 `var` 先进行声明。
在Andy的解释器中:
@@ -762,29 +763,6 @@ code: undefined symbol "i"
```
-默认不定长参数
-
-这个解释器在运行时,函数不会将超出参数表的那部分不定长参数放到默认的`arg`中。所以你如果不定义`arg`就使用它,那你只会得到`undefined symbol`。
-
-```javascript
-var f=func(){
- println(arg)
-}
-f(1,2,3);
-```
-
-编译结果:
-
-```javascript
-code: undefined symbol "arg"
- --> test.nas:2:15
- |
-2 | println(arg)
- | ^ undefined symbol "arg"
-```
-
-
-
## __堆栈追踪信息__

diff --git a/src/nasal_builtin.cpp b/src/nasal_builtin.cpp
index 3f0326f..a097810 100644
--- a/src/nasal_builtin.cpp
+++ b/src/nasal_builtin.cpp
@@ -1210,12 +1210,6 @@ var builtin_millisec(var* local, gc& ngc) {
return var::num(res);
}
-var builtin_sysargv(var* local, gc& ngc) {
- var res = ngc.alloc(vm_vec);
- res.vec().elems = ngc.env_argv;
- return res;
-}
-
var builtin_gcextend(var* local, gc& ngc) {
var type = local[1];
if (type.type!=vm_str) {
@@ -1356,7 +1350,6 @@ nasal_builtin_table builtin[] = {
{"__costatus", builtin_costatus},
{"__corun", builtin_corun},
{"__millisec", builtin_millisec},
- {"__sysargv", builtin_sysargv},
{"__gcextd", builtin_gcextend},
{"__logtime", builtin_logtime},
{"__ghosttype", builtin_ghosttype},
diff --git a/src/nasal_builtin.h b/src/nasal_builtin.h
index 2169a3a..7dd25bc 100644
--- a/src/nasal_builtin.h
+++ b/src/nasal_builtin.h
@@ -124,7 +124,6 @@ var builtin_coyield(var*, gc&);
var builtin_costatus(var*, gc&);
var builtin_corun(var*, gc&);
var builtin_millisec(var*, gc&);
-var builtin_sysargv(var*, gc&);
var builtin_gcextend(var*, gc&);
var builtin_logtime(var*, gc&);
var builtin_ghosttype(var*, gc&);
diff --git a/src/nasal_codegen.cpp b/src/nasal_codegen.cpp
index f84c53e..683fb54 100644
--- a/src/nasal_codegen.cpp
+++ b/src/nasal_codegen.cpp
@@ -211,6 +211,16 @@ void codegen::func_gen(function* node) {
// search symbols first, must use after loading parameters
// or the location of symbols will change and cause fatal error
find_symbol(block);
+ // add special varibale "arg", which is used to store overflowed args
+ // but if dynamic parameter is declared, this variable will be useless
+ // for example:
+ // var f = func(a) {print(arg)}
+ // f(1, 2, 3);
+ // then the arg is [2, 3], because 1 is accepted by "a"
+ // so in fact "f" is the same as:
+ // var f = func(a, arg...) {return(arg)}
+ add_symbol("arg");
+
in_iterloop.push(0);
block_gen(block);
in_iterloop.pop();
@@ -1094,13 +1104,7 @@ const error& codegen::compile(parse& parse, linker& import) {
// add special symbol globals, which is a hash stores all global variables
add_symbol("globals");
- // add special symbol arg here, which is used to store function arguments
- // for example:
- // var f = func(a) {print(arg)}
- // f(1, 2, 3);
- // then the arg is [2, 3], because 1 is accepted by "a"
- // so in fact "f" is the same as:
- // var f = func(a, arg...) {return(arg)}
+ // add special symbol arg here, which is used to store command line args
add_symbol("arg");
find_symbol(parse.tree()); // search symbols first
diff --git a/src/nasal_lexer.cpp b/src/nasal_lexer.cpp
index a85c252..1e3d541 100644
--- a/src/nasal_lexer.cpp
+++ b/src/nasal_lexer.cpp
@@ -7,43 +7,43 @@
#include "nasal_lexer.h"
bool lexer::skip(char c) {
- return c==' '||c=='\n'||c=='\t'||c=='\r'||c==0;
+ return c==' ' || c=='\n' || c=='\t' || c=='\r' || c==0;
}
bool lexer::is_id(char c) {
- return (c=='_')||('a'<=c && c<='z')||('A'<=c&&c<='Z')||(c<0);
+ return (c=='_') || ('a'<=c && c<='z') || ('A'<=c && c<='Z') || (c<0);
}
bool lexer::is_hex(char c) {
- return ('0'<=c&&c<='9')||('a'<=c&&c<='f')||('A'<=c && c<='F');
+ return ('0'<=c && c<='9') || ('a'<=c && c<='f') || ('A'<=c && c<='F');
}
bool lexer::is_oct(char c) {
- return '0'<=c&&c<='7';
+ return '0'<=c && c<='7';
}
bool lexer::is_dec(char c) {
- return '0'<=c&&c<='9';
+ return '0'<=c && c<='9';
}
bool lexer::is_str(char c) {
- return c=='\''||c=='\"'||c=='`';
+ return c=='\'' || c=='\"' || c=='`';
}
bool lexer::is_single_opr(char c) {
return (
- c=='('||c==')'||c=='['||c==']'||
- c=='{'||c=='}'||c==','||c==';'||
- c==':'||c=='?'||c=='`'||c=='@'||
- c=='%'||c=='$'||c=='\\'
+ c=='(' || c==')' || c=='[' || c==']' ||
+ c=='{' || c=='}' || c==',' || c==';' ||
+ c==':' || c=='?' || c=='`' || c=='@' ||
+ c=='%' || c=='$' || c=='\\'
);
}
bool lexer::is_calc_opr(char c) {
return (
- c=='='||c=='+'||c=='-'||c=='*'||
- c=='!'||c=='/'||c=='<'||c=='>'||
- c=='~'||c=='|'||c=='&'||c=='^'
+ c=='=' || c=='+' || c=='-' || c=='*' ||
+ c=='!' || c=='/' || c=='<' || c=='>' ||
+ c=='~' || c=='|' || c=='&' || c=='^'
);
}
@@ -54,8 +54,10 @@ void lexer::skip_note() {
void lexer::err_char() {
++column;
- char c=res[ptr++];
- err.err("lexer", {line, column-1, line, column, filename}, "invalid character 0x"+chrhex(c));
+ char c = res[ptr++];
+ err.err("lexer",
+ {line, column-1, line, column, filename},
+ "invalid character 0x"+chrhex(c));
err.fatal("lexer", "fatal error occurred, stop");
}
@@ -81,220 +83,241 @@ void lexer::open(const std::string& file) {
}
tok lexer::get_type(const std::string& str) {
- return typetbl.count(str)?typetbl.at(str):tok::null;
+ return typetbl.count(str)? typetbl.at(str):tok::null;
}
std::string lexer::utf8_gen() {
- std::string str="";
+ std::string str = "";
while(ptr");
+ err.err("lexer",
+ {line, column-1, line, column, filename},
+ "invalid utf-8 <"+utf_info+">");
err.fatal("lexer", "fatal error occurred, stop");
}
- str+=tmp;
- column+=2; // may have some problems because not all the unicode takes 2 space
+ str += tmp;
+ column += 2; // may have some problems because not all the unicode takes 2 space
}
return str;
}
token lexer::id_gen() {
- u32 begin_line=line;
- u32 begin_column=column;
- std::string str="";
+ u32 begin_line = line;
+ u32 begin_column = column;
+ std::string str = "";
while(ptr [0~9][0~9]*(.[0~9]*)(e|E(+|-)0|[1~9][0~9]*)
- std::string str="";
+ std::string str = "";
while(ptr=res.size()) {
- err.err("lexer", {begin_line, begin_column, line, column, filename}, "get EOF when generating string");
+ err.err("lexer",
+ {begin_line, begin_column, line, column, filename},
+ "get EOF when generating string");
return {{begin_line, begin_column, line, column, filename}, tok::str, str};
}
++column;
- if (begin=='`' && str.length()!=1) {
- err.err("lexer", {begin_line, begin_column, line, column, filename}, "\'`\' is used for string including one character");
+
+ // if is not utf8, 1+utf8_hdchk should be 1
+ if (begin=='`' && str.length()!=1+utf8_hdchk(str[0])) {
+ err.err("lexer",
+ {begin_line, begin_column, line, column, filename},
+ "\'`\' is used for string including one character");
}
return {{begin_line, begin_column, line, column, filename}, tok::str, str};
}
token lexer::single_opr() {
- u32 begin_line=line;
- u32 begin_column=column;
- std::string str(1,res[ptr]);
+ u32 begin_line = line;
+ u32 begin_column = column;
+ std::string str(1, res[ptr]);
++column;
- tok type=get_type(str);
+ tok type = get_type(str);
if (type==tok::null) {
- err.err("lexer", {begin_line, begin_column, line, column, filename}, "invalid operator `"+str+"`");
+ err.err("lexer",
+ {begin_line, begin_column, line, column, filename},
+ "invalid operator `"+str+"`");
}
++ptr;
return {{begin_line, begin_column, line, column, filename}, type, str};
}
token lexer::dots() {
- u32 begin_line=line;
- u32 begin_column=column;
- std::string str=".";
+ u32 begin_line = line;
+ u32 begin_column = column;
+ std::string str = ".";
if (ptr+2=res.size()) {
@@ -328,6 +351,6 @@ const error& lexer::scan(const std::string& file) {
}
}
toks.push_back({{line, column, line, column, filename}, tok::eof, ""});
- res="";
+ res = "";
return err;
}
diff --git a/src/nasal_misc.cpp b/src/nasal_misc.cpp
index 954ae53..4f01d0b 100644
--- a/src/nasal_misc.cpp
+++ b/src/nasal_misc.cpp
@@ -85,14 +85,14 @@ bool is_superh() {
}
f64 hex2f(const char* str) {
- f64 ret=0;
+ f64 ret = 0;
for(; *str; ++str) {
if ('0'<=*str && *str<='9') {
- ret=ret*16+(*str-'0');
+ ret = ret*16+(*str-'0');
} else if ('a'<=*str && *str<='f') {
- ret=ret*16+(*str-'a'+10);
+ ret = ret*16+(*str-'a'+10);
} else if ('A'<=*str && *str<='F') {
- ret=ret*16+(*str-'A'+10);
+ ret = ret*16+(*str-'A'+10);
} else {
return nan("");
}
@@ -101,9 +101,9 @@ f64 hex2f(const char* str) {
}
f64 oct2f(const char* str) {
- f64 ret=0;
+ f64 ret = 0;
while('0'<=*str && *str<'8') {
- ret=ret*8+(*str++-'0');
+ ret = ret*8+(*str++-'0');
}
if (*str) {
return nan("");
@@ -118,9 +118,9 @@ f64 oct2f(const char* str) {
// but this also makes 0.1+0.2==0.3,
// not another result that you may get in other languages.
f64 dec2f(const char* str) {
- f64 ret=0,negative=1,num_pow=0;
+ f64 ret = 0, negative = 1, num_pow = 0;
while('0'<=*str && *str<='9') {
- ret=ret*10+(*str++-'0');
+ ret = ret*10+(*str++-'0');
}
if (!*str) {
return ret;
@@ -129,10 +129,10 @@ f64 dec2f(const char* str) {
if (!*++str) {
return nan("");
}
- num_pow=0.1;
+ num_pow = 0.1;
while('0'<=*str && *str<='9') {
- ret+=num_pow*(*str++-'0');
- num_pow*=0.1;
+ ret += num_pow*(*str++-'0');
+ num_pow *= 0.1;
}
if (!*str) {
return ret;
@@ -145,14 +145,14 @@ f64 dec2f(const char* str) {
return nan("");
}
if (*str=='-' || *str=='+') {
- negative=(*str++=='-'? -1:1);
+ negative = (*str++=='-'? -1:1);
}
if (!*str) {
return nan("");
}
- num_pow=0;
+ num_pow = 0;
while('0'<=*str && *str<='9') {
- num_pow=num_pow*10+(*str++-'0');
+ num_pow = num_pow*10+(*str++-'0');
}
if (*str) {
return nan("");
@@ -161,27 +161,27 @@ f64 dec2f(const char* str) {
}
f64 str2num(const char* str) {
- bool negative=false;
- f64 res=0;
+ bool negative = false;
+ f64 res = 0;
if (*str=='-' || *str=='+') {
- negative=(*str++=='-');
+ negative = (*str++=='-');
}
if (!*str) {
return nan("");
}
if (str[0]=='0' && str[1]=='x') {
- res=hex2f(str+2);
+ res = hex2f(str+2);
} else if (str[0]=='0' && str[1]=='o') {
- res=oct2f(str+2);
+ res = oct2f(str+2);
} else {
- res=dec2f(str);
+ res = dec2f(str);
}
- return negative?-res:res;
+ return negative? -res:res;
}
i32 utf8_hdchk(const char head) {
// RFC-2279 but now we use RFC-3629 so nbytes is less than 4
- const u8 c=(u8)head;
+ const u8 c = (u8)head;
if ((c>>5)==0x06) { // 110x xxxx (10xx xxxx)^1
return 1;
}
@@ -195,36 +195,36 @@ i32 utf8_hdchk(const char head) {
}
std::string chrhex(const char c) {
- const char hextbl[]="0123456789abcdef";
- return {hextbl[(c&0xf0)>>4],hextbl[c&0x0f]};
+ const char hextbl[] = "0123456789abcdef";
+ return {hextbl[(c&0xf0)>>4], hextbl[c&0x0f]};
}
std::string rawstr(const std::string& str, const usize maxlen) {
std::string ret("");
- for(auto i:str) {
+ for(auto i : str) {
// windows doesn't output unicode normally, so we output the hex
if (is_windows() && i<=0) {
- ret+="\\x"+chrhex(i);
+ ret += "\\x"+chrhex(i);
continue;
}
switch(i) {
- case '\0': ret+="\\0"; break;
- case '\a': ret+="\\a"; break;
- case '\b': ret+="\\b"; break;
- case '\t': ret+="\\t"; break;
- case '\n': ret+="\\n"; break;
- case '\v': ret+="\\v"; break;
- case '\f': ret+="\\f"; break;
- case '\r': ret+="\\r"; break;
- case '\033':ret+="\\e"; break;
- case '\"': ret+="\\\"";break;
- case '\'': ret+="\\\'";break;
- case '\\': ret+="\\\\";break;
- default: ret+=i; break;
+ case '\0': ret += "\\0"; break;
+ case '\a': ret += "\\a"; break;
+ case '\b': ret += "\\b"; break;
+ case '\t': ret += "\\t"; break;
+ case '\n': ret += "\\n"; break;
+ case '\v': ret += "\\v"; break;
+ case '\f': ret += "\\f"; break;
+ case '\r': ret += "\\r"; break;
+ case '\033':ret += "\\e"; break;
+ case '\"': ret += "\\\""; break;
+ case '\'': ret += "\\\'"; break;
+ case '\\': ret += "\\\\"; break;
+ default: ret += i; break;
}
}
if (maxlen && ret.length()>maxlen) {
- ret=ret.substr(0,maxlen)+"...";
+ ret = ret.substr(0,maxlen)+"...";
}
return ret;
}
\ No newline at end of file
diff --git a/src/nasal_vm.cpp b/src/nasal_vm.cpp
index 27e12e1..11057ee 100644
--- a/src/nasal_vm.cpp
+++ b/src/nasal_vm.cpp
@@ -8,26 +8,28 @@ void vm::init(
const std::vector& filenames,
const std::vector& argv
) {
- cnum=nums.data();
- cstr=strs.data();
- bytecode=code.data();
- files=filenames.data();
+ cnum = nums.data();
+ cstr = strs.data();
+ bytecode = code.data();
+ files = filenames.data();
/* set canary and program counter */
- ctx.pc=0;
- ctx.localr=ctx.memr=nullptr;
- ctx.funcr=ctx.upvalr=nil;
- ctx.canary=stack+STACK_DEPTH-1; // stack[STACK_DEPTH-1]
- ctx.top=stack;
- ctx.stack=stack;
+ ctx.pc = 0;
+ ctx.localr = nullptr;
+ ctx.memr = nullptr;
+ ctx.funcr = nil;
+ ctx.upvalr = nil;
+ ctx.canary = stack+STACK_DEPTH-1; // stack[STACK_DEPTH-1]
+ ctx.top = stack;
+ ctx.stack = stack;
/* clear main stack */
- for(u32 i=0;i "< "< entry:0x"<=ctx.canary) {
die("stack overflow");
@@ -640,14 +643,14 @@ inline void vm::o_callfv() {
var dynamic = nil;
if (func.dpara>=0) { // load dynamic arguments
dynamic = ngc.alloc(vm_vec);
- for(u32 i=psize;i=1;--i) { // load arguments
+ for(u32 i = min_size; i>=1; --i) { // load arguments
local[i] = local[i-1];
}
local[0] = func.local[0];// load "me"
+
// load local scope & default arguments
- for(u32 i=min_size+1;i=0) {
- local[psize+1] = dynamic;
- }
+ local[func.dpara>=0? psize+1:func.lsize-1] = dynamic;
ctx.top[0] = ctx.upvalr;
(++ctx.top)[0] = var::addr(ctx.localr);
(++ctx.top)[0] = var::ret(ctx.pc);
- ctx.pc=func.entry-1;
+ ctx.pc = func.entry-1;
ctx.localr = local;
ctx.upvalr = nil;
}
@@ -912,9 +914,6 @@ inline void vm::o_ret() {
ctx.funcr = ctx.top[0];
ctx.top[0] = ret; // rewrite func with returned value
- // reset "arg"
- stack[1] = nil;
-
if (up.type==vm_upval) { // synchronize upvalue
auto& upval = up.upval();
auto size = func.func().lsize;
diff --git a/std/lib.nas b/std/lib.nas
index f137fa3..e8680c3 100644
--- a/std/lib.nas
+++ b/std/lib.nas
@@ -478,7 +478,7 @@ var os = {
# runtime gives us some functions that we could manage it manually.
var runtime = {
# command line arguments
- argv: func() {return __sysargv;},
+ argv: func() {return globals.arg;},
gc: {
extend: func(type) {return __gcextd;}
}
diff --git a/test/globals_test.nas b/test/globals_test.nas
index bb55d7f..c698b33 100644
--- a/test/globals_test.nas
+++ b/test/globals_test.nas
@@ -16,9 +16,12 @@ globals.test_func();
var f = func() {
println(arg);
+ func() {println(arg);}(114, 514, 1919, 810);
+ println(arg);
}
f(1, 2, 3);
+# command line arguments
println(arg);
println(globals.arg);
\ No newline at end of file
diff --git a/test/sample.nas b/test/sample.nas
index 8fb0c42..5865f17 100644
--- a/test/sample.nas
+++ b/test/sample.nas
@@ -1,16 +1,16 @@
# This file is written by Andy Ross, and is protected by GPLv2.0
# A no-op function used below to get this file to run. Ignore and read on...
-dummyFunc = func { 1 }
+var dummyFunc = func { 1 }
#
# Literal numbers can be decimal, exponential, or hex constants. All
# numbers are stored internally as IEEE double-precision values.
#
-n1 = 3;
-n2 = 3.14;
-n3 = 6.023e23;
-n3 = 0x123456;
+var n1 = 3;
+var n2 = 3.14;
+var n3 = 6.023e23;
+var n3 = 0x123456;
#
# Two identical string literals with different quotes. Double quotes
@@ -19,14 +19,14 @@ n3 = 0x123456;
# whitespace like newlines). Double quotes handle the following
# C-like escapes: \n \r \t \xnn \"
#
-s1 = 'Andy\'s "computer" has a C:\righteous\newstuff directory.';
-s2 = "Andy's \"computer\" has a C:\\righteous\\newstuff directory.";
+var s1 = 'Andy\'s "computer" has a C:\righteous\newstuff directory.';
+var s2 = "Andy's \"computer\" has a C:\\righteous\\newstuff directory.";
#
# Literal lists use square brackets with a comma-separated expression
# list.
#
-list1 = ["a", "b", 1, 2];
+var list1 = ["a", "b", 1, 2];
#
# Literal hashes (or objects -- same thing) use curlies and colons to
@@ -35,8 +35,8 @@ list1 = ["a", "b", 1, 2];
# to use symbols, lookup tables of other types will be more
# comfortable with literals.
#
-hash1 = { name : "Andy", job : "Hacker" };
-EnglishEspanol = { "one" : "uno", "two": "dos", "blue" : "azul" };
+var hash1 = { name : "Andy", job : "Hacker" };
+var EnglishEspanol = { "one" : "uno", "two": "dos", "blue" : "azul" };
#
# Both vectors and hashes use square brackets for the lookup operation:
@@ -50,7 +50,7 @@ hash1["name"] == "Andy";
# (anonymous) function argument to the local "log_message" variable.
# There is no function declaration syntax in Nasal.
#
-log_message = func {
+var log_message = func {
print(arg[0]);
}
@@ -58,10 +58,10 @@ log_message = func {
# You can also pass named arguments to a function, thus saving the
# typing and performance costs of extracting them from the arg array.
#
-sqrt = dummyFunc;
-dist = func(x1, y1, x2, y2) {
- dx = x2-x1;
- dy = y2-y1;
+var sqrt = dummyFunc;
+var dist = func(x1, y1, x2, y2) {
+ var dx = x2-x1;
+ var dy = y2-y1;
return sqrt(dx*dx + dy*dy);
}
dist(0,0,1,1); # == sqrt(2)
@@ -71,14 +71,14 @@ dist(0,0,1,1); # == sqrt(2)
# default value must be a scalar (number, string, function, nil) and
# not a mutable composite object (list, hash).
#
-read = func(bytes, flags=0) { }
+var read = func(bytes, flags=0) { }
#
# Any extra arguments after the named list are placed in the "arg"
# vector as above. You can rename this to something other than "arg"
# by specifying a final argument name with an ellipsis:
#
-listify = func(elements...) { return elements; }
+var listify = func(elements...) { return elements; }
listify(1, 2, 3, 4); # returns a list: [1, 2, 3, 4]
#
@@ -87,7 +87,7 @@ listify(1, 2, 3, 4); # returns a list: [1, 2, 3, 4]
# good practice in general, although it is not required. Note that
# this is not a "declaration", just a qualifier on the "=" operator.
#
-innerFunc = func {
+var innerFunc = func {
for(var dist=0; dist<100; dist += 1) {
# Does not interfere with the "dist" symbol defined above
}
@@ -99,26 +99,26 @@ innerFunc = func {
# what the ?: does in C. The last semicolon in a code block is
# optional, to make this prettier.
#
-abs = func(n) { if(n<0) { -n } else { n } }
+var abs = func(n) { if(n<0) { -n } else { n } }
#
# But for those who don't like typing, the ternary operator works like
# you expect:
#
-abs = func(n) { n < 0 ? -n : n }
+var abs = func(n) { n < 0 ? -n : n }
#
# Nasal supports a "nil" value for use as a null pointer equivalent.
# It can be tested for equality, matching only other nils.
#
-listNode = { data : ["what", "ever"], next : nil };
+var listNode = { data : ["what", "ever"], next : nil };
#
# Nasal's binary boolean operators are "and" and "or", unlike C.
# unary not is still "!" however. They short-circuit like you expect
#
-toggle = 0;
-a = nil;
+var toggle = 0;
+var a = nil;
if(a and a.field == 42) {
toggle = !toggle; # doesn't crash when a is nil
}
@@ -129,24 +129,24 @@ if(a and a.field == 42) {
# takes a local variable name as its first argument and a vector as
# its second.
#
-doSomething = dummyFunc;
+var doSomething = dummyFunc;
-stillGoing = 0;
+var stillGoing = 0;
while(stillGoing) { doSomething(); }
-for(i=0; i < 3; i = i+1) {
+for(var i=0; i < 3; i = i+1) {
elem = list1[i];
doSomething(elem);
}
-foreach(elem; list1) { doSomething(elem) } # Shorthand for above
+foreach(var elem; list1) { doSomething(elem) } # Shorthand for above
#
# There is also a "forindex", which is like foreach except that it
# assigns the index of each element, instead of the value, to the loop
# variable.
#
-forindex(i; list1) { doSomething(list1[i]); }
+forindex(var i; list1) { doSomething(list1[i]); }
#
# Define a class object with one method, one field and one "new"
@@ -155,10 +155,10 @@ forindex(i; list1) { doSomething(list1[i]); }
# appropriately. Member functions can get their local object (the
# equivalent of the "this" pointer in C++) as the "me" variable.
#
-Class1 = {};
+var Class1 = {};
Class1.new = func {
- obj = { parents : [Class1],
+ var obj = { parents : [Class1],
count : 0 };
return obj;
}
@@ -168,7 +168,7 @@ Class1.getcount = func {
return me.count;
}
-c = Class1.new();
+var c = Class1.new();
print(c.getcount(), "\n"); # prints 1
print(c.getcount(), "\n"); # prints 2
print(c.getcount(), "\n"); # prints 3
@@ -177,20 +177,20 @@ print(c.getcount(), "\n"); # prints 3
# But *set* operations always go to the local object. You can't
# corrupt a parent class via OOP operations on its instances (but you
# *can* get to it via hand-inspection of the parents arrays).
-c2 = Class1.new();
-c2.getcount() = func { 12345 }; # custom "derived" function!
+var c2 = Class1.new();
+c2.getcount = func { return 12345 }; # custom "derived" function!
print(c2.getcount(), "\n"); # prints 12345
-print(c1.getcount(), "\n"); # prints 4, Class1.getcount is unchanged
+print(c.getcount(), "\n"); # prints 4, Class1.getcount is unchanged
#
# This creates an identical class using alternative syntax.
#
-Class2 = {
+var Class2 = {
new : func {
- obj = {};
- obj.parents = [Class2];
- obj.count = 0;
+ var obj = {};
+ obj.parents = [Class2];
+ obj.count = 0;
return obj;
},
getcount : func {
@@ -206,7 +206,7 @@ Class2 = {
# C (although note that there is no nul termination -- get the length
# with size()):
#
-string = "abcdefghijklmnopqrstuvwxyz";
+var string = "abcdefghijklmnopqrstuvwxyz";
var ascii_sum = 0;
for(var i=0; i= `A` and mutable[i] <= `Z`) {
@@ -237,14 +237,14 @@ print(ascii_lc("ABCDEFG"), "\n"); # prints "abcdefg"
# Advanced vectors: The lookup index can be negative, where -1
# indicates the last element in the vector (or string).
#
-next_to_last = list1[-2];
+var next_to_last = list1[-2];
#
# Remember that strings look syntactically like vectors of bytes; so
# conversely, the "~" concatenation operator works equally well to
# concatenate vectors:
#
-joined_list = [1, 2, 3] ~ [4, 5, 6];
+var joined_list = [1, 2, 3] ~ [4, 5, 6];
###
### Now some fun examples:
@@ -254,9 +254,9 @@ joined_list = [1, 2, 3] ~ [4, 5, 6];
# Make a "inverted index" hash out of a vector that returns the index
# for each element.
#
-invert = func(vec) {
- hash = {};
- for(i=0; i 0) {
- k = ks[0];
+ var k = ks[0];
result = result ~ k ~ ":" ~ dump(o[k]);
}
for(i=1; i