From bc9361344ae2825a2c4460318e96cae55f9af941 Mon Sep 17 00:00:00 2001 From: vendethiel Date: Tue, 14 Nov 2017 15:56:14 +0100 Subject: [PATCH] Implement return void, #218 --- lib/ast.js | 19 ++++++++++++++++++- lib/lexer.js | 7 ++++++- lib/parser.js | 3 ++- src/ast.co | 11 +++++++++++ src/lexer.co | 7 ++++++- test/compilation.co | 3 +++ test/function.co | 4 ++++ 7 files changed, 50 insertions(+), 4 deletions(-) diff --git a/lib/ast.js b/lib/ast.js index c06c32730..54785a5bd 100644 --- a/lib/ast.js +++ b/lib/ast.js @@ -1,4 +1,4 @@ -var Node, Negatable, Block, Atom, Literal, Var, Key, Index, Chain, Call, List, Obj, Prop, Arr, Unary, Binary, Assign, Import, Of, Existence, Fun, Class, Super, Parens, Splat, Jump, Throw, Return, While, For, Try, Switch, Case, If, Label, Pipe, JS, Util, Vars, DECLS, ref$, UTILS, LEVEL_TOP, LEVEL_PAREN, LEVEL_LIST, LEVEL_COND, LEVEL_OP, LEVEL_CALL, PREC, TAB, ID, SIMPLENUM, slice$ = [].slice, replace$ = ''.replace; +var Node, Negatable, Block, Atom, Literal, Var, Key, Index, Chain, Call, List, Obj, Prop, Arr, Unary, Binary, Assign, Import, Of, Existence, Fun, Class, Super, Parens, Splat, Jump, Throw, Return, ReturnVoid, While, For, Try, Switch, Case, If, Label, Pipe, JS, Util, Vars, DECLS, ref$, UTILS, LEVEL_TOP, LEVEL_PAREN, LEVEL_LIST, LEVEL_COND, LEVEL_OP, LEVEL_CALL, PREC, TAB, ID, SIMPLENUM, slice$ = [].slice, replace$ = ''.replace; (Node = function(){ throw Error('unimplemented'); }).prototype = { @@ -2623,6 +2623,23 @@ exports.Return = Return = (function(superclass){ }; return Return; }(Jump)); +exports.ReturnVoid = ReturnVoid = (function(superclass){ + ReturnVoid.displayName = 'ReturnVoid'; + var prototype = extend$(ReturnVoid, superclass).prototype, constructor = ReturnVoid; + function ReturnVoid(it){ + var this$ = this instanceof ctor$ ? this : new ctor$; + this$.it = it; + return this$; + } function ctor$(){} ctor$.prototype = prototype; + prototype.getJump = THIS; + prototype.compileNode = function(o){ + if (!this.it) { + this.carp("Can't hush a return without a value"); + } + return "return void " + this.it.compile(o, LEVEL_PAREN) + ";"; + }; + return ReturnVoid; +}(Jump)); exports.While = While = (function(superclass){ While.displayName = 'While'; var prototype = extend$(While, superclass).prototype, constructor = While; diff --git a/lib/lexer.js b/lib/lexer.js index bd41bc2a6..9f1e10fa6 100644 --- a/lib/lexer.js +++ b/lib/lexer.js @@ -124,10 +124,15 @@ exports.doID = function(code, index){ return input.length; } switch (id) { + case 'void': + if (last[0] === 'HURL' && last[1] === 'return') { + last[1] = 'returnvoid'; + return 4; + } + // fallthrough case 'true': case 'false': case 'null': - case 'void': case 'arguments': case 'debugger': tag = 'LITERAL'; diff --git a/lib/parser.js b/lib/parser.js index 19a2e7e05..26db44e0c 100644 --- a/lib/parser.js +++ b/lib/parser.js @@ -3,7 +3,8 @@ yy: {}, symbols_: {"error":2,"Head":3,"ID":4,"STRNUM":5,"LITERAL":6,"Parenthetical":7,"List":8,"PARAM(":9,"ArgList":10,")PARAM":11,"->":12,"Block":13,"FUNCTION":14,"CALL(":15,")CALL":16,"IF":17,"Expression":18,"Else":19,"INDENT":20,"IfLines":21,"DEDENT":22,"LoopHead":23,"SWITCH":24,"Cases":25,"DEFAULT":26,"TRY":27,"CATCH":28,"FINALLY":29,"CLASS":30,"Chain":31,"OptExtends":32,"OptImplements":33,"LET":34,"WITH":35,"FOR":36,"DOT":37,"Key":38,"?":39,"[":40,"]":41,"{":42,"PropList":43,"}":44,"LABEL":45,"KeyBase":46,"Args":47,"OptComma":48,"Arg":49,",":50,"NEWLINE":51,"...":52,"Lines":53,"Line":54,"<-":55,"COMMENT":56,"ASSIGN":57,"IMPORT":58,"CREMENT":59,"UNARY":60,"+-":61,"^":62,"COMPARE":63,"LOGIC":64,"MATH":65,"SHIFT":66,"BITWISE":67,"RELATION":68,"|>":69,"!?":70,"POST_IF":71,"DO":72,"WHILE":73,"HURL":74,"JUMP":75,"EXTENDS":76,"DECL":77,"Exprs":78,"KeyValue":79,"Prop":80,":":81,"Props":82,"(":83,"Body":84,")":85,"ELSE":86,"OF":87,"BY":88,"IN":89,"FROM":90,"TO":91,"CASE":92,"IMPLEMENTS":93,"Root":94,"$accept":0,"$end":1}, terminals_: {2:"error",4:"ID",5:"STRNUM",6:"LITERAL",9:"PARAM(",11:")PARAM",12:"->",14:"FUNCTION",15:"CALL(",16:")CALL",17:"IF",20:"INDENT",22:"DEDENT",24:"SWITCH",26:"DEFAULT",27:"TRY",28:"CATCH",29:"FINALLY",30:"CLASS",34:"LET",35:"WITH",36:"FOR",37:"DOT",39:"?",40:"[",41:"]",42:"{",44:"}",45:"LABEL",50:",",51:"NEWLINE",52:"...",55:"<-",56:"COMMENT",57:"ASSIGN",58:"IMPORT",59:"CREMENT",60:"UNARY",61:"+-",62:"^",63:"COMPARE",64:"LOGIC",65:"MATH",66:"SHIFT",67:"BITWISE",68:"RELATION",69:"|>",70:"!?",71:"POST_IF",72:"DO",73:"WHILE",74:"HURL",75:"JUMP",76:"EXTENDS",77:"DECL",81:":",83:"(",85:")",86:"ELSE",87:"OF",88:"BY",89:"IN",90:"FROM",91:"TO",92:"CASE",93:"IMPLEMENTS"}, productions_: [0,[3,1],[3,1],[3,1],[3,1],[3,1],[3,5],[3,5],[3,4],[3,4],[3,3],[3,3],[3,5],[3,2],[3,4],[3,2],[3,2],[3,4],[3,6],[3,4],[3,5],[3,4],[3,5],[3,3],[3,3],[31,1],[31,3],[31,3],[31,4],[31,2],[8,3],[8,3],[8,4],[8,4],[38,1],[38,1],[46,1],[46,1],[10,0],[10,2],[47,1],[47,3],[47,4],[47,4],[47,6],[49,1],[49,2],[49,1],[48,0],[48,1],[53,0],[53,1],[53,3],[53,2],[54,1],[54,2],[54,5],[54,1],[54,1],[13,3],[18,1],[18,3],[18,5],[18,3],[18,5],[18,2],[18,2],[18,3],[18,3],[18,3],[18,2],[18,2],[18,2],[18,4],[18,3],[18,3],[18,3],[18,3],[18,3],[18,3],[18,3],[18,3],[18,3],[18,3],[18,2],[18,3],[18,2],[18,4],[18,2],[18,4],[18,1],[18,1],[18,2],[18,3],[18,2],[18,2],[18,4],[78,1],[78,3],[79,1],[79,1],[79,3],[79,3],[79,4],[79,4],[80,3],[80,5],[80,1],[80,3],[80,2],[80,2],[80,2],[80,1],[43,0],[43,2],[82,1],[82,3],[82,4],[82,4],[7,3],[84,1],[84,1],[84,3],[19,0],[19,2],[19,5],[23,4],[23,6],[23,4],[23,6],[23,6],[23,8],[23,2],[23,4],[21,3],[21,4],[25,3],[25,4],[32,2],[32,0],[33,2],[33,0],[94,1]], -performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$) { +performAction: function anonymous(yytext,yyleng,yylineno,yy,yystate,$$ +/*``*/) { var $0 = $$.length - 1; switch (yystate) { diff --git a/src/ast.co b/src/ast.co index 612045ba5..a7029c121 100644 --- a/src/ast.co +++ b/src/ast.co @@ -1608,6 +1608,17 @@ class exports.Return extends Jump compileNode: (o) -> "return#{ if @it then ' ' + that.compile o, LEVEL_PAREN else '' };" +#### Return void +class exports.ReturnVoid extends Jump + (@it) ~> + + getJump: THIS + + compileNode: (o) -> + @carp "Can't hush a return without a value" unless @it + "return void #{ @it.compile o, LEVEL_PAREN };" + + #### While # The traditional `while`/`for`/`do` loop. # Returns an array of values collected from the last expression when requested. diff --git a/src/lexer.co b/src/lexer.co index 2adacbc82..ce81a10f5 100644 --- a/src/lexer.co +++ b/src/lexer.co @@ -109,7 +109,12 @@ exports import return input.length # keywords switch id - case \true \false \null \void \arguments \debugger then tag = \LITERAL + case \void + if last.0 is \HURL and last.1 is \return + last.1 = \returnvoid + return 4 + fallthrough + case \true \false \null \arguments \debugger then tag = \LITERAL case \new \do \typeof \delete then tag = \UNARY case \return \throw then tag = \HURL case \break \continue then tag = \JUMP diff --git a/test/compilation.co b/test/compilation.co index 99e509643..1b151e716 100644 --- a/test/compilation.co +++ b/test/compilation.co @@ -183,3 +183,6 @@ Coco.compile 'class A; class B; class C' # [livescript#279](https://github.com/gkz/LiveScript/issues/279) Coco.compile \################################################################ + +# Can't hush an empty return +compileThrows "Can't hush a return without a value" 1 '-> return void' diff --git a/test/function.co b/test/function.co index c6460423d..f899bedd3 100644 --- a/test/function.co +++ b/test/function.co @@ -499,3 +499,7 @@ let eq a, b eq c, d eq e, f + + +### can hush a return +eq void, do -> return void true