<div dir="ltr"><br><div><br></div><div>Hi all,</div><div><br></div><div>Interesting discussion! I'm not much of types person, but I guess (/would propose) that in any case runtime execution should never depend on types. I'm pretty sure you're aiming for this (seeing the discussion above), but (if it's actually the case) it would be good to make this *very* explicit in the spec. </div><div><br></div><div>Regarding the "syntactic vinegar", I wonder why this syntax was chosen in the first place. Is it really unparseable with single [], or even <>? For instance, as far as I can see, the only place where [] are used are lineups. You could require at least 1 space to occur before a lineup, and disallow a space before the [] actual generic type arg. I assume type args on call sites will always be after the selector name (or the first keyword component). This would work with both prefix ops -[Int] 3, infix ops 1 +[Int,Int] 2, and keyword messages if[Bool,Block,Block] () then {} else {}.</div><div><br></div><div>James and I  also had some discussion of the offside rule. I have an implementation of it, that seems to make sense. Below you'll find an excerpt of my test suite; perhaps they can be added to a/the central grace test suite?</div><div>Basically these functions parse a CodeSequence using parse code, containing a single or multiple statements, and then asserts the number of statements is some value (isExpr(...) is equal to countStats(...) == 1). You can ignore the apostrophes, that's just Rascal's way of allowing nice multi-line strings.  </div><div><br></div><div>To summarize the rules as I've implemented them as post-parse filters:</div><div>- Reject a Code statement that contains any syntactic element below it with the same or less indentation, *except* the closing curly }. </div><div>- Reject a Code declaration <span style="line-height:1.5">that contains any syntactic element below it with the same or less indentation, *except* the closing curly }. </span></div><div><span style="line-height:1.5">- Reject a CodeSequence where the constituent Code elements are on the same line, unless the left element ends with a semicolon.</span></div><div><span style="line-height:1.5">- Reject an Expression which is binaryOtherOp where the lhs is also a binaryOtherOp but its operator is not the same as the current operator.</span></div><div><br></div><div>One source of contention was zigzag, which failed in one implementation, but was ok in another (@James, please correct me if I'm wrong). </div><div><br></div><div>You can find Rascal's grace grammar here: <a href="https://github.com/cwi-swat/grace-grammar/blob/offside2/src/DynGrace.rsc">https://github.com/cwi-swat/grace-grammar/blob/offside2/src/DynGrace.rsc</a></div><div>Disambiguation starts at line 273, which is ugly, verbose and (too) slow now, -- we'll just have to wait until our data dependent parsing stuff gets integrated into Rascal :-D</div><div><br></div><div>I've also attached a screenshot showing how nested methods, and defs/vars in traits are treated as static errors, rather than semantic errors.</div><div><br></div><div>Cheers!</div><div><br></div><div>Tijs</div><div><br></div><div><br></div><div><div>test bool keywordMessage0() </div><div>  = isExpr(parseCode("if (x) then {y} </div><div>                     '  else {z}"));</div><div><br></div><div>test bool keywordMessage01() </div><div>  = isExpr(parseCode("if (x) then {y} else </div><div>                     '  {z}"));</div><div><br></div><div>test bool zigzag() </div><div>  = isExpr(parseCode("if (x)</div><div>                     '   then {foo}</div><div>                     ' elsif (x)</div><div>                     '    then {bar}</div><div>                     ' elsif (x)</div><div>                     '    then {baz}"));</div><div><br></div><div>test bool keywordMessageBla() </div><div>  = isExpr(parseCode("match 1</div><div>                     '   case 2</div><div>                     '   do (x)</div><div>                     '   case 3</div><div>                     '   do (x)"));</div><div><br></div><div><br></div><div>test bool keywordMessage1() </div><div>  = isExpr(parseCode("if (x) then {y} else {z}"));</div><div><br></div><div>test bool keywordMessage2() </div><div>  = isExpr(parseCode("if (x) </div><div>                     '  then {y} </div><div>                     '  else {z}"));</div><div><br></div><div>test bool keywordMessage3() </div><div>  = isExpr(parseCode("if (x) </div><div>                     '  then {y} </div><div>                     '    else {z}"));</div><div><br></div><div>test bool keywordMessage4() </div><div>  = countStats(parseCode("if (x) then {y} else {z}")) == 1;</div><div>  </div><div>Tree pw() =   parseCode("if (x) </div><div>                        'then {y} </div><div>                        'else {z}");</div><div>  </div><div>test bool keywordMessage5() </div><div>  = countStats(parseCode("if (x) </div><div>                         'then {y} </div><div>                         'else {z}")) == 3;</div><div>  </div><div>test bool keywordMessage6() </div><div>  = countStats(parseCode("if (x) </div><div>                         '  then {y} </div><div>                         'else {z}")) == 2;</div><div><br></div><div>test bool keywordMessage7() </div><div>  = isExpr(parseCode("if (x) then {</div><div>                     '  y </div><div>                     '} else {</div><div>                     '  z</div><div>                     '}"));</div><div><br></div><div>test bool keywordMessage7NoCurlies() </div><div>  = isExpr(parseCode("if (x) then </div><div>                     '  3 </div><div>                     ' else </div><div>                     '  4"));</div><div> </div><div>test bool semicolonSingleLine()</div><div>  = countStats(parseCode("a; b")) == 2;</div><div><br></div><div>test bool semicolonMultiLine()</div><div>  = countStats(parseCode("a;\n b")) == 2;</div><div><br></div><div>test bool semicolonMultiLineStat()</div><div>  = countStats(parseCode("if (x) then </div><div>                     '  3 </div><div>                     ' else </div><div>                     '  4; x")) == 2;</div><div><br></div><div>test bool curlyOpenOnNextLine()</div><div>  = countStats(parseCode("foo\n  {x}")) == 1;</div><div><br></div><div><br></div><div>test bool otherOp1() </div><div>  = isExpr(parseCode("1 ++ 2"));</div><div><br></div><div><br></div><div>test bool otherOp2() </div><div>  = isExpr(parseCode("1 </div><div>                     '  ++ 2"));</div><div><br></div><div><br></div><div>test bool otherOp3() </div><div>  = countStats(parseCode("1 </div><div>                         '++ 2")) == 2;</div><div><br></div><div>test bool otherOp3() </div><div>  = countStats(parseCode("1 ++ </div><div>                         ' 2")) == 1;</div><div><br></div><div>test bool otherOp4() </div><div>  = countStats(parseCode("1 ++ </div><div>                         ' 2 ++ </div><div>                         '   3")) == 1;</div><div><br></div><div>test bool otherOp5() </div><div>  = countStats(parseCode("1 ++ </div><div>                         ' 2 </div><div>                         '++ 3")) == 2;</div><div><br></div><div>test bool otherOp6() </div><div>  = countStats(parseCode("1  </div><div>                         ' ++ 2 </div><div>                         ' ++ 3")) == 1;</div><div><br></div><div><br></div><div>test bool plusOp1() </div><div>  = isExpr(parseCode("1 + 2"));</div><div><br></div><div><br></div><div>test bool plusOp2() </div><div>  = isExpr(parseCode("1 </div><div>                     '  + 2"));</div><div><br></div><div>// is there no builtin unary plus?</div><div>//test bool plusOp3() </div><div>//  = countStats(parseCode("1 </div><div>//                         '+ 2")) == 2;</div><div><br></div><div>test bool plusOp3() </div><div>  = countStats(parseCode("1 + </div><div>                         ' 2")) == 1;</div><div>  </div><div>  </div><div>test bool otherOpPrecedence1() </div><div>  = isLeftAssoc(parseExp("1 ++ 2 ++ 3")); </div><div>  </div><div>  </div><div>  </div><div>test bool otherOpPrecedence2() </div><div>  = expectParseError(() { parseExp("1 -- 2 ++ 3"); });</div><div>   </div><div><br></div><div>test bool otherOpParens() </div><div>  = expectParseError(() { </div><div>      parseCode("(x </div><div>                ' ++ y)");</div><div>    });</div><div>    </div><div>    // should succeed</div><div>test bool someVar1() </div><div>  = countStats(parseCode("var x := y</div><div>                         '  ++ z")) == 1;</div><div><br></div><div>test bool someVar2() </div><div>  = countStats(parseCode("var x := y</div><div>                         '          ++ z")) == 1;</div><div> </div><div>test bool prefixOp1()</div><div>  = isExpr(parseCode("++</div><div>                     '  3"));  </div><div><br></div><div>test bool prefixOp2()</div><div>  = isExpr(parseCode("++</div><div>                     ' 3"));  </div><div>  </div><div>test bool prefixOp3()</div><div>  = countStats(parseCode("a</div><div>                         '++</div><div>                         '  3")) == 2;</div></div><div><br></div><div><br></div><div><br></div><br><div class="gmail_quote"><div dir="ltr">On Mon, Jul 25, 2016 at 10:53 AM James Noble <<a href="mailto:kjx@ecs.vuw.ac.nz">kjx@ecs.vuw.ac.nz</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">> It’s simple.  If you want explicit type parameters, you put them in, using the ordinary parameter syntax and specifying that their type is Type.  If you don’t want explicit type parameters, you do what is shown in the pdf extract .<br>
<br>
ahh OK, yep.   I did remember you telling me that, the excerpt from the manual<br>
didn't cover it that's all<br>
<br>
> In Emerald, the number of arguments must always be the same as the number of parameters.  There are no defaults.<br>
<br>
other than these "implicits",  But Emerald wasn't "gradually typed".<br>
<br>
<br>
On reflection - I wonder if I was (somewhat) confusing things in my last comments.  There is a (big) difference between a dialect inferring types or type parameters and using them (locally, statically) to check things. and the<br>
dialect (if it could) or core compiler (which can)  using inference to<br>
(globally, dynamically) populate the reified generic parameters.<br>
<br>
The catch is that if these two things are different we're back to Java generic erasure, basically.<br>
<br>
This is tricky, and I don't think we've thought through it enough.<br>
I fear no-one has.   We should ask Jeremy & Ron again.<br>
<br>
james</blockquote></div></div>