constructor.getParameterTypes());
if(dataType.constructors.length == 1 && (
dataType.getTypeDesc() == null ||
- dataType.constructors[0].javaName.equals(MethodBuilderBase.getClassName(dataType.getTypeDesc()))))
+ (dataType.constructors[0].javaName != null &&
+ dataType.constructors[0].javaName.equals(MethodBuilderBase.getClassName(dataType.getTypeDesc())))))
sclConstructor.setOnlyConstructor(true);
value.setValue(sclConstructor);
value.setType(constructor.getType());
typeMap.put(name.name, valueTypeAst);
}
+ THashMap<String, EVar> exportMap = null;
+ if(moduleHeader != null && moduleHeader.export != null) {
+ exportMap = new THashMap<String, EVar>();
+ for(EVar export : moduleHeader.export)
+ if(exportMap.put(export.name, export) != null)
+ errorLog.log(export.location, "The symbol " + export.name + " is exported multiple times.");
+ }
+
for(String name : valueDefinitionsAst.getValueNames()) {
ArrayList<DValueAst> defs = valueDefinitionsAst.getDefinition(name);
try {
for(DAnnotationAst annotation : annotations) {
handleAnnotation(value, defs, annotation);
}
+ if(exportMap != null && exportMap.remove(name) == null)
+ value.addProperty(PrivateProperty.INSTANCE);
} catch(RuntimeException e) {
errorLog.setExceptionPosition(defs.get(0).location);
throw e;
}
}
+ if(exportMap != null)
+ for(EVar export : exportMap.values())
+ errorLog.log(export.location, "The symbol " + export.name + " is not defined in the module.");
for(String name : relationDefinitionsAst.getRelationNames()) {
ArrayList<DRelationAst> definitions = relationDefinitionsAst.getDefinition(name);
if(definitions.size() > 1) {
}
}
else if(annotation.id.text.equals("@private")) {
+ if(moduleHeader != null && moduleHeader.export != null)
+ errorLog.log(annotation.location, "Annotation @private is not used when module header contains export property.");
value.addProperty(PrivateProperty.INSTANCE);
}
else if(annotation.id.text.equals("@deprecated")) {
package org.simantics.scl.compiler.elaboration.expressions.annotations;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
import org.simantics.scl.compiler.constants.StringConstant;
+import org.simantics.scl.compiler.elaboration.expressions.EListLiteral;
import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
import org.simantics.scl.compiler.elaboration.expressions.EStringLiteral;
import org.simantics.scl.compiler.elaboration.expressions.EVar;
}
return null;
}
+
+ public static List<EVar> extractIdentifierList(Expression expression) {
+ if(expression instanceof EVar || expression instanceof EStringLiteral || expression instanceof ELiteral)
+ return Collections.singletonList(new EVar(expression.location, extractString(expression)));
+ else if(expression instanceof EListLiteral) {
+ Expression[] components = ((EListLiteral)expression).getComponents();
+ EVar[] items = new EVar[components.length];
+ for(int i=0;i<components.length;++i) {
+ String value = extractString(components[i]);
+ if(value == null)
+ return null;
+ items[i] = new EVar(components[i].location, value);
+ }
+ return Arrays.asList(items);
+ }
+ return null;
+ }
}
package org.simantics.scl.compiler.internal.header;
+import java.util.List;
+
+import org.simantics.scl.compiler.elaboration.expressions.EVar;
import org.simantics.scl.compiler.elaboration.expressions.annotations.AnnotationUtils;
import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment;
import org.simantics.scl.compiler.errors.ErrorLog;
public long classLoaderLocation;
public String defaultLocalName;
public boolean fields;
+ public List<EVar> export;
private void read(ErrorLog errorLog, DModuleHeader header) {
for(FieldAssignment assignment : header.fields)
classLoaderLocation = assignment.location;
}
break;
+ case "export":
+ if(assignment.value == null)
+ errorLog.log(assignment.location, "Property export needs to be given a string list value.");
+ else {
+ export = AnnotationUtils.extractIdentifierList(assignment.value);
+ if(export == null)
+ errorLog.log(assignment.value.location, "Expected a list of exported items.");
+ }
+ break;
case "defaultLocalName":
if(assignment.value == null)
errorLog.log(assignment.location, "Property defaultLocalName needs to be given a string value.");
}
break;
case "fields":
+ if(assignment.value != null)
+ errorLog.log(assignment.location, "No value expected for property fields.");
this.fields = true;
break;
default:
package org.simantics.scl.compiler.tests;
+import org.junit.Test;
+
public class ActiveTests extends TestBase {
public ActiveTests() { super("scl"); }
//@Test public void Bug6989() { test(); }
+
}
@Test public void Maybe4() { test(); }
@Test public void MissingEffect() { test(); }
@Test public void MissingMethod() { test(); }
+ @Test public void ModuleExport() { test(); }
@Test public void ModuleInitialization() { test(); }
@Test public void MonadBug1() { test(); }
@Test public void Monads1() { test(); }
--- /dev/null
+// module FooBar
+module {
+ export = [foo]
+}
+foo = "foo"
+bar = "bar"
+--
+import "FooBar"
+main = foo
+--
+foo
+--
+import "FooBar"
+main = bar
+--
+2:8-2:11: Couldn't resolve bar.
\ No newline at end of file