Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

support for => in named arg lists to fix #466

  • Loading branch information...
commit aca4c15536ac3b0a0f19f56baa8cc1a2be3754cf 1 parent caea4d9
@gavinking gavinking authored FroMage committed
View
94 Ceylon.g
@@ -1528,10 +1528,10 @@ sequencedArgument returns [SequencedArgument sequencedArgument]
namedArgument returns [NamedArgument namedArgument]
: compilerAnnotations
- (
+ (
namedSpecifiedArgument
{ $namedArgument = $namedSpecifiedArgument.specifiedArgument; }
- |
+ |
namedArgumentDeclaration
{ $namedArgument = $namedArgumentDeclaration.declaration; }
)
@@ -1540,11 +1540,14 @@ namedArgument returns [NamedArgument namedArgument]
;
namedSpecifiedArgument returns [SpecifiedArgument specifiedArgument]
- : memberNameDeclaration
+ : memberName
{ $specifiedArgument = new SpecifiedArgument(null);
- $specifiedArgument.setIdentifier($memberNameDeclaration.identifier); }
- specifier
- { $specifiedArgument.setSpecifierExpression($specifier.specifierExpression); }
+ $specifiedArgument.setIdentifier($memberName.identifier); }
+ (
+ specifier
+ { $specifiedArgument.setSpecifierExpression($specifier.specifierExpression); }
+ )?
+ { expecting=SEMICOLON; }
SEMICOLON
{ $specifiedArgument.setEndToken($SEMICOLON); }
;
@@ -1589,8 +1592,19 @@ voidOrInferredMethodArgument returns [MethodArgument declaration]
parameters
{ $declaration.addParameterList($parameters.parameterList); }
)*
- block
- { $declaration.setBlock($block.block); }
+ (
+ block
+ { $declaration.setBlock($block.block); }
+ |
+ (
+ lazySpecifier
+ { $declaration.setSpecifierExpression($lazySpecifier.specifierExpression); }
+ )?
+ { expecting=SEMICOLON; }
+ SEMICOLON
+ { expecting=-1; }
+ { $declaration.setEndToken($SEMICOLON); }
+ )
//-> ^(METHOD_ARGUMENT VOID_MODIFIER memberName parameters* block)
;
@@ -1600,8 +1614,19 @@ inferredGetterArgument returns [AttributeArgument declaration]
{ $declaration.setType(new ValueModifier($VALUE_MODIFIER)); }
memberNameDeclaration
{ $declaration.setIdentifier($memberNameDeclaration.identifier); }
- block
- { $declaration.setBlock($block.block); }
+ (
+ block
+ { $declaration.setBlock($block.block); }
+ |
+ (
+ lazySpecifier
+ { $declaration.setSpecifierExpression($lazySpecifier.specifierExpression); }
+ )?
+ { expecting=SEMICOLON; }
+ SEMICOLON
+ { expecting=-1; }
+ { $declaration.setEndToken($SEMICOLON); }
+ )
//-> ^(ATTRIBUTE_ARGUMENT VALUE_MODIFIER memberName block)
;
@@ -1622,9 +1647,48 @@ typedMethodOrGetterArgument returns [TypedArgument declaration]
{ marg.addParameterList($parameters.parameterList); }
)+
)?
- block
- { marg.setBlock($block.block);
- aarg.setBlock($block.block); }
+ (
+ block
+ { marg.setBlock($block.block);
+ aarg.setBlock($block.block); }
+ |
+ (
+ lazySpecifier
+ { marg.setSpecifierExpression($lazySpecifier.specifierExpression);
+ aarg.setSpecifierExpression($lazySpecifier.specifierExpression); }
+ )?
+ { expecting=SEMICOLON; }
+ SEMICOLON
+ { expecting=-1; }
+ { $declaration.setEndToken($SEMICOLON); }
+ )
+ //-> ^(METHOD_ARGUMENT unionType memberName parameters+ memberBody)
+ //-> ^(ATTRIBUTE_ARGUMENT unionType memberName memberBody)
+ ;
+
+untypedMethodOrGetterArgument returns [TypedArgument declaration]
+ @init { MethodArgument marg = new MethodArgument(null);
+ marg.setType(new FunctionModifier(null));
+ AttributeArgument aarg = new AttributeArgument(null);
+ aarg.setType(new ValueModifier(null));
+ $declaration=aarg; }
+ : memberName
+ { marg.setIdentifier($memberName.identifier);
+ aarg.setIdentifier($memberName.identifier); }
+ (
+ { $declaration = marg; }
+ (
+ parameters
+ { marg.addParameterList($parameters.parameterList); }
+ )+
+ )?
+ lazySpecifier
+ { marg.setSpecifierExpression($lazySpecifier.specifierExpression);
+ aarg.setSpecifierExpression($lazySpecifier.specifierExpression); }
+ { expecting=SEMICOLON; }
+ SEMICOLON
+ { expecting=-1; }
+ { $declaration.setEndToken($SEMICOLON); }
//-> ^(METHOD_ARGUMENT unionType memberName parameters+ memberBody)
//-> ^(ATTRIBUTE_ARGUMENT unionType memberName memberBody)
;
@@ -1638,6 +1702,8 @@ namedArgumentDeclaration returns [NamedArgument declaration]
{ $declaration=$voidOrInferredMethodArgument.declaration; }
| inferredGetterArgument
{ $declaration=$inferredGetterArgument.declaration; }
+ | untypedMethodOrGetterArgument
+ { $declaration=$untypedMethodOrGetterArgument.declaration; }
;
//special rule for syntactic predicate
@@ -1658,7 +1724,7 @@ iterableArgumentStart
//special rule for syntactic predicates
specificationStart
- : LIDENTIFIER (SPECIFY|COMPUTE)
+ : LIDENTIFIER parameters* (SPECIFY|COMPUTE)
;
parExpression returns [Expression expression]
View
8 Ceylon.nodes
@@ -608,7 +608,7 @@ argument list."
EXPRESSION
Parameter parameter;)
-^(FUNCTION_ARGUMENT: TERM
+^(FUNCTION_ARGUMENT:TERM
TYPE type
PARAMETER_LIST*
EXPRESSION
@@ -624,10 +624,12 @@ argument list."
abstract TypedDeclaration declarationModel;)
^(METHOD_ARGUMENT:TYPED_ARGUMENT
PARAMETER_LIST*
- BLOCK
+ BLOCK?
+ SPECIFIER_EXPRESSION?
Method declarationModel;)
^(ATTRIBUTE_ARGUMENT:TYPED_ARGUMENT
- BLOCK
+ BLOCK?
+ SPECIFIER_EXPRESSION?
Getter declarationModel;)
^(OBJECT_ARGUMENT:TYPED_ARGUMENT
EXTENDED_TYPE?
View
39 src/com/redhat/ceylon/compiler/typechecker/analyzer/ControlFlowVisitor.java
@@ -100,12 +100,17 @@ public void visit(Tree.AttributeGetterDefinition that) {
@Override
public void visit(Tree.AttributeArgument that) {
- boolean c = beginReturnScope(true);
- boolean d = beginDefiniteReturnScope();
- super.visit(that);
- checkDefiniteReturn(that, name(that.getIdentifier()));
- endDefiniteReturnScope(d);
- endReturnScope(c);
+ if (that.getSpecifierExpression()==null) {
+ boolean c = beginReturnScope(true);
+ boolean d = beginDefiniteReturnScope();
+ super.visit(that);
+ checkDefiniteReturn(that, name(that.getIdentifier()));
+ endDefiniteReturnScope(d);
+ endReturnScope(c);
+ }
+ else {
+ super.visit(that);
+ }
}
private void checkDefiniteReturn(Node that, String name) {
@@ -137,14 +142,19 @@ public void visit(Tree.MethodDefinition that) {
@Override
public void visit(Tree.MethodArgument that) {
- boolean c = beginReturnScope(true);
- boolean d = beginDefiniteReturnScope();
- super.visit(that);
- if (!(that.getType() instanceof Tree.VoidModifier)) {
- checkDefiniteReturn(that, name(that.getIdentifier()));
+ if (that.getSpecifierExpression()==null) {
+ boolean c = beginReturnScope(true);
+ boolean d = beginDefiniteReturnScope();
+ super.visit(that);
+ if (!(that.getType() instanceof Tree.VoidModifier)) {
+ checkDefiniteReturn(that, name(that.getIdentifier()));
+ }
+ endDefiniteReturnScope(d);
+ endReturnScope(c);
+ }
+ else {
+ super.visit(that);
}
- endDefiniteReturnScope(d);
- endReturnScope(c);
}
@Override
@@ -154,6 +164,9 @@ public void visit(Tree.AttributeDeclaration that) {
checkExecutableStatementAllowed(that.getSpecifierOrInitializerExpression());
super.visit(that);
}
+ else {
+ super.visit(that);
+ }
}
@Override
View
9 src/com/redhat/ceylon/compiler/typechecker/analyzer/DeclarationVisitor.java
@@ -1009,7 +1009,14 @@ public void visit(Tree.SpecifierStatement that) {
exitScope(o);
}
-
+ /*@Override
+ public void visit(Tree.SpecifiedArgument that) {
+ Specification s = new Specification();
+ visitElement(that, s);
+ Scope o = enterScope(s);
+ super.visit(that);
+ exitScope(o);
+ }*/
@Override
public void visit(Tree.SatisfiesCondition that) {
View
92 src/com/redhat/ceylon/compiler/typechecker/analyzer/ExpressionVisitor.java
@@ -871,11 +871,23 @@ private void checkKeyValueType(Tree.Variable key, Tree.Variable value,
}
@Override public void visit(Tree.AttributeArgument that) {
- Tree.Type rt = beginReturnScope(that.getType());
- Declaration od = beginReturnDeclaration(that.getDeclarationModel());
- super.visit(that);
- endReturnDeclaration(od);
- endReturnScope(rt, that.getDeclarationModel());
+ Tree.SpecifierExpression se = that.getSpecifierExpression();
+ if (se==null) {
+ Tree.Type rt = beginReturnScope(that.getType());
+ Declaration od = beginReturnDeclaration(that.getDeclarationModel());
+ super.visit(that);
+ endReturnDeclaration(od);
+ endReturnScope(rt, that.getDeclarationModel());
+ }
+ else {
+ super.visit(that);
+ inferType(that, se);
+ if (that.getType()!=null) {
+ checkType(that.getType().getTypeModel(),
+ that.getDeclarationModel().getName(),
+ se, 2100);
+ }
+ }
}
@Override public void visit(Tree.AttributeSetterDefinition that) {
@@ -910,11 +922,25 @@ private void checkKeyValueType(Tree.Variable key, Tree.Variable value,
}
@Override public void visit(Tree.MethodArgument that) {
- Tree.Type rt = beginReturnScope(that.getType());
- Declaration od = beginReturnDeclaration(that.getDeclarationModel());
- super.visit(that);
- endReturnDeclaration(od);
- endReturnScope(rt, that.getDeclarationModel());
+ Tree.SpecifierExpression se = that.getSpecifierExpression();
+ if (se==null) {
+ Tree.Type rt = beginReturnScope(that.getType());
+ Declaration od = beginReturnDeclaration(that.getDeclarationModel());
+ super.visit(that);
+ endReturnDeclaration(od);
+ endReturnScope(rt, that.getDeclarationModel());
+ }
+ else {
+ super.visit(that);
+ Tree.Expression e = se.getExpression();
+ if (e!=null) {
+ ProducedType returnType = e.getTypeModel();
+ inferFunctionType(that, returnType);
+ if (that.getType()!=null) {
+ checkFunctionType(returnType, that.getType());
+ }
+ }
+ }
}
@Override public void visit(Tree.ClassDefinition that) {
@@ -1005,6 +1031,20 @@ private void inferType(Tree.TypedDeclaration that,
}
}
+ private void inferType(Tree.AttributeArgument that,
+ Tree.SpecifierOrInitializerExpression spec) {
+ if (that.getType() instanceof Tree.LocalModifier) {
+ Tree.LocalModifier local = (Tree.LocalModifier) that.getType();
+ if (spec!=null) {
+ setType(local, spec, that);
+ }
+ else {
+// local.addError("could not infer type of: " +
+// name(that.getIdentifier()));
+ }
+ }
+ }
+
private void inferFunctionType(Tree.TypedDeclaration that, ProducedType et) {
if (that.getType() instanceof Tree.FunctionModifier) {
Tree.FunctionModifier local = (Tree.FunctionModifier) that.getType();
@@ -1014,6 +1054,15 @@ private void inferFunctionType(Tree.TypedDeclaration that, ProducedType et) {
}
}
+ private void inferFunctionType(Tree.MethodArgument that, ProducedType et) {
+ if (that.getType() instanceof Tree.FunctionModifier) {
+ Tree.FunctionModifier local = (Tree.FunctionModifier) that.getType();
+ if (et!=null) {
+ setFunctionType(local, et, that);
+ }
+ }
+ }
+
private void inferDefiniteType(Tree.Variable that,
Tree.SpecifierExpression se) {
if (that.getType() instanceof Tree.LocalModifier) {
@@ -1207,6 +1256,20 @@ private void setType(Tree.LocalModifier local,
}
}
+ private void setType(Tree.LocalModifier local,
+ Tree.SpecifierOrInitializerExpression s,
+ Tree.AttributeArgument that) {
+ Expression e = s.getExpression();
+ if (e!=null) {
+ ProducedType type = e.getTypeModel();
+ if (type!=null) {
+ ProducedType t = unit.denotableType(type);
+ local.setTypeModel(t);
+ that.getDeclarationModel().setType(t);
+ }
+ }
+ }
+
private void setFunctionType(Tree.FunctionModifier local,
ProducedType et, Tree.TypedDeclaration that) {
ProducedType t = unit.denotableType(et);
@@ -1214,6 +1277,13 @@ private void setFunctionType(Tree.FunctionModifier local,
that.getDeclarationModel().setType(t);
}
+ private void setFunctionType(Tree.FunctionModifier local,
+ ProducedType et, Tree.MethodArgument that) {
+ ProducedType t = unit.denotableType(et);
+ local.setTypeModel(t);
+ that.getDeclarationModel().setType(t);
+ }
+
@Override public void visit(Tree.Throw that) {
super.visit(that);
Expression e = that.getExpression();
@@ -1910,7 +1980,7 @@ private void checkInvocationArguments(Tree.InvocationExpression that,
checkPositionalArguments(pl, prf, that.getPositionalArgumentList());
}
if ( that.getNamedArgumentList()!=null ) {
- if(pl.isNamedParametersSupported()) {
+ if (pl.isNamedParametersSupported()) {
that.getNamedArgumentList().getNamedArgumentList().setParameterList(pl);
checkNamedArguments(pl, prf, that.getNamedArgumentList());
}
View
74 test/main/function/FunctionTypes.ceylon
@@ -33,6 +33,8 @@ void higher2(String[] strings, void f(String str)) {
@error f("hello", 2);
}
+Integer higher3(Integer f(Float x)) => f(0.0);
+
String str(Float f) => f.string;
Float curried(Integer x)(Float y) => x+y;
@@ -112,6 +114,78 @@ void method() {
higher2({"goodbye"}, (String s) print(s));
higher2({"goodbye"}, (String s) print(s));
+ higher2 {
+ strings = {"goodbye"};
+ function f(String s) => s.size;
+ };
+ higher2 {
+ strings = {"goodbye"};
+ Integer f(String s) => s.size;
+ };
+
+ higher2 {
+ strings = {"goodbye"};
+ void f(String s) => print(s);
+ };
+ higher2 {
+ strings = {"goodbye"};
+ function f(String s) => print(s);
+ };
+ higher2 {
+ strings = {"goodbye"};
+ String f(String s) => s;
+ };
+ higher2 {
+ strings = {"goodbye"};
+ Integer f(String s) => s.size;
+ };
+ higher2 {
+ strings = {"goodbye"};
+ @error Integer f(String s) => print(s);
+ };
+ higher2 {
+ strings = {"goodbye"};
+ @error Integer f(Integer i) => i;
+ };
+ higher2 {
+ strings = {"goodbye"};
+ @error function f(Integer i) => print(i);
+ };
+
+ higher2 {
+ strings = {"goodbye"};
+ f(String s) => s.size;
+ };
+
+
+ higher3 {
+ function f(Float f) { return f.integer; }
+ };
+ higher3 {
+ function f(Float f) => f.integer;
+ };
+ higher3 {
+ Integer f(Float f) => f.integer;
+ };
+ higher3 {
+ @error void f(Float f) {}
+ };
+ higher3 {
+ @error function f(Float f) { return f; }
+ };
+ higher3 {
+ @error function f(Float f) => f;
+ };
+ higher3 {
+ @error Float f(Float f) => f;
+ };
+ higher3 {
+ @error Integer f(Float f, String s) => f.integer;
+ };
+ higher3 {
+ @error Integer f(String s) => s.size;
+ };
+
@error print(s);
@type:"Callable<Float,Tuple<Float,Float,Empty>>" curried(1);
View
55 test/main/function/methodargs.ceylon
@@ -0,0 +1,55 @@
+void testShortcutMethodSpec(){
+ Float f(Float g(Float x));
+ f(Float g(Float x)) => g(1.0);
+ f {
+ g(Float x) => x*2.0;
+ };
+ f {
+ g = (Float x) x*2.0;
+ };
+ f {
+ function g(Float x) => x*2.0;
+ };
+ //f {
+ // @error value g(Float x) => x*2.0;
+ //};
+ f {
+ Float g(Float x) => x*2.0;
+ };
+ f {
+ @error g(Integer x) => x*2.0;
+ };
+ f {
+ @error g = (Integer x) x*2.0;
+ };
+ f {
+ @error function g(Integer x) => x*2.0;
+ };
+ f {
+ @error g(Float x) => x.integer*2;
+ };
+ f {
+ @error g = (Float x) x.integer*2;
+ };
+ f {
+ @error function g(Float x) => x.integer*2;
+ };
+
+ Float h(Float x);
+ h(Float x) => x;
+ h {
+ x => 5.0;
+ };
+ h {
+ value x => 5.0;
+ };
+ h {
+ @error function x => 5.0;
+ };
+ h {
+ Float x => 5.0;
+ };
+ h {
+ @error x => 5;
+ };
+}
Please sign in to comment.
Something went wrong with that request. Please try again.