From aec283f0b4999dfb71193aa694b97d12b8dda106 Mon Sep 17 00:00:00 2001 From: Onoshko Dan Date: Fri, 15 Aug 2014 04:19:06 +0700 Subject: [PATCH] operator `?` to sign an argument as not-required int sqr(int x) => x ** 2; sqr(2); // 4 sqr(); // Exception int sqrt(int x?) => x ** 2; sqr(); // NaN --- README.md | 20 ++++++++++---------- lib/ast.js | 2 +- lib/parse.js | 27 ++++++++++++++++++--------- lib/std.js | 10 ++++++++-- lib/translate.js | 29 ++++++++++++++++++++++------- 5 files changed, 59 insertions(+), 29 deletions(-) diff --git a/README.md b/README.md index b8966d3a..1b4e96ae 100644 --- a/README.md +++ b/README.md @@ -378,16 +378,7 @@ Future plans int data.getFriendsCount() => this.friends.length; - operator `?.`. status: done -- Negate array accessor ( getter ) - - arr[-1]; // last element - - only for static negate index, for other cases you can use `%` unary prefix: - - int index = -10; - arr[%index] = 34; // arr[index %% arr.length]; - -- operator `?` to sign an argument as not-required +- operator `?` to sign an argument as not-required. status: done int sqr(int x) => x ** 2; @@ -397,6 +388,15 @@ Future plans int sqrt(int x?) => x ** 2; sqr(); // NaN +- Negate array accessor ( getter ) + + arr[-1]; // last element + + only for static negate index, for other cases you can use `%` unary prefix: + + int index = -10; + arr[%index] = 34; // arr[index %% arr.length]; + - static typing - `@use` expressions diff --git a/lib/ast.js b/lib/ast.js index 78b52787..fc9d7804 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -421,7 +421,7 @@ Cola.AST_Namedarg = Cola.DEFNODE("Namedarg", "start end name value", { } }, Cola.AST_SymbolRef); -Cola.AST_ArgDef = Cola.DEFNODE("ArgDef", "start end name type argtype defval", { +Cola.AST_ArgDef = Cola.DEFNODE("ArgDef", "start end name type argtype defval required", { $iscola: true, $documentation: "A function argument expression", $propdoc: { diff --git a/lib/parse.js b/lib/parse.js index 6e9ca066..6fd3c360 100644 --- a/lib/parse.js +++ b/lib/parse.js @@ -1310,14 +1310,22 @@ Cola.Parser.prototype.for_in = function (init) { }; Cola.Parser.prototype.as_funcarg = function(splatedexist) { - var name = this.as_symbol(Cola.AST_SymbolFunarg), type = name, argtype = 'positional', defval = new Cola.AST_Noop(); + var name = this.as_symbol(Cola.AST_SymbolFunarg), type = name, argtype = 'positional', defval = new Cola.AST_Noop, required = true; + if(this.is("name")) name = this.as_symbol(Cola.AST_SymbolFunarg); - if(this.is("punc", "...")){ + + if(this.is("operator", "?")){ + required = false; + this.next(); + } + + if(this.is("punc", "...") && required){ if(splatedexist) this.token_error(this.S, "Unexpected token: splated argument can be only one."); if(type != name && type.name != "Array") this.token_error(this.S, "Unexpected token: splated argument must have `Array` type."); + required = false; this.next(); argtype = "splated"; - } else if(this.is("operator", "=")){ + } else if(this.is("operator", "=") && required){ this.next(); defval = this.expression(false); } else if(this.is("punc",":")){ @@ -1329,12 +1337,13 @@ Cola.Parser.prototype.as_funcarg = function(splatedexist) { } return new Cola.AST_ArgDef({ - name : name, - type : name.type = (argtype == "splated" ? "Array" : type == name ? "dynamic" : type.name), - argtype : argtype, - defval : defval, - start : type.start, - end : this.prev() + name : name, + type : name.type = (argtype == "splated" ? "Array" : type == name ? "dynamic" : type.name), + required : required, + argtype : argtype, + defval : defval, + start : type.start, + end : this.prev() }); }; diff --git a/lib/std.js b/lib/std.js index c64622fc..a5d902d5 100644 --- a/lib/std.js +++ b/lib/std.js @@ -121,12 +121,18 @@ Cola._ColaRuntime$$func_set_named_args = function _ColaRuntime$$func_set_named_a } } Cola._ColaRuntime$$func_set_named_args.i = 10; -Cola._ColaRuntime$$arguments_def = { i : 11 }; + +Cola._ColaRuntime$$error = function _ColaRuntime$$error(_error) { + throw new Error(_error); +}; +Cola._ColaRuntime$$error.i = 11; + +Cola._ColaRuntime$$arguments_def = { i : 12 }; Cola.$_cola = Cola._ColaRuntime$$is + Cola._ColaRuntime$$isnt + Cola._ColaRuntime$$modulo + Cola._ColaRuntime$$isset + Cola._ColaRuntime$$isntset + Cola._ColaRuntime$$clone + Cola._ColaRuntime$$array_last + Cola._ColaRuntime$$array_range + - Cola._ColaRuntime$$array_asplice + Cola._ColaRuntime$$func_named_args + Cola._ColaRuntime$$func_set_named_args + + Cola._ColaRuntime$$array_asplice + Cola._ColaRuntime$$func_named_args + Cola._ColaRuntime$$func_set_named_args + Cola._ColaRuntime$$error + "var arguments;"; Cola.Compressor.StdFuncs = { diff --git a/lib/translate.js b/lib/translate.js index eed87f3e..70b77939 100644 --- a/lib/translate.js +++ b/lib/translate.js @@ -1044,7 +1044,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){ node.argnames.forEach(function(val, i){ if(val.argtype == "positional"){ - if(val.defval instanceof Cola.AST_Noop && onfront) pos++, node.argnames[i] = val.name; + if(val.defval instanceof Cola.AST_Noop && onfront && !val.required) pos++, node.argnames[i] = val.name; else { onfront = false; delQueue.push(i); @@ -1073,7 +1073,7 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){ posed.forEach(function(val, i){ var pos = val.pos; val = val.val; - + console.log(val); if(val.argtype == "splated"){ aftersplated = 0; props.definitions.push(new Cola.AST_VarDef({ @@ -1086,20 +1086,35 @@ Cola.AST_Toplevel.prototype.toJavaScript = function(options){ } else - if(val.defval instanceof Cola.AST_Noop) props.definitions.push(Cola.Constructions.PosedVarDef(val.name, val.type, pos, aftersplated++)); - else props.definitions.push(Cola.Constructions.PosedWithDefsVarDef(val.name, val.type, val.defval, pos, aftersplated++)); + if(val.defval instanceof Cola.AST_Noop && !val.required) + props.definitions.push(Cola.Constructions.PosedVarDef(val.name, val.type, pos, aftersplated++)); + else if(val.defval instanceof Cola.AST_Noop && val.required){ + _ColaRuntime$$hash[Cola._ColaRuntime$$error.i] = true; + props.definitions.push(Cola.Constructions.PosedWithDefsVarDef(val.name, val.type, new Cola.AST_Call({ + args : [new Cola.AST_String({ value : "Argument `" + val.name.name + "` is required!" })], + expression : new Cola.AST_SymbolRef({ name : '_ColaRuntime$$error' }) + }), pos, aftersplated++)); + } else + props.definitions.push(Cola.Constructions.PosedWithDefsVarDef(val.name, val.type, val.defval, pos, aftersplated++)); }); named.forEach(function(val, i){ - if(val.defval instanceof Cola.AST_Noop) props.definitions.push(new Cola.AST_VarDef({ + if(val.defval instanceof Cola.AST_Noop && !val.required) props.definitions.push(new Cola.AST_VarDef({ type : val.type, name : new Cola.AST_SymbolVar(val.name), value : new Cola.AST_Dot({ expression : new Cola.AST_SymbolRef({ name : 'arguments' }), property : val.name.name }) - })); - else props.definitions.push(Cola.Constructions.NamedVarDef(val.name, val.type, val.defval, val.name.name)); + })); + else if(val.defval instanceof Cola.AST_Noop && val.required){ + _ColaRuntime$$hash[Cola._ColaRuntime$$error.i] = true; + props.definitions.push(Cola.Constructions.NamedVarDef(val.name, val.type, new Cola.AST_Call({ + args : [new Cola.AST_String({ value : "Argument `" + val.name.name + "` is required!" })], + expression : new Cola.AST_SymbolRef({ name : '_ColaRuntime$$error' }) + }), val.name.name)); + } else + props.definitions.push(Cola.Constructions.NamedVarDef(val.name, val.type, val.defval, val.name.name)); }); if(delQueue.length != 0 || named.length != 0) node.body.unshift(new Cola.AST_Var(props));