import org.cojen.classfile.TypeDesc;
import org.simantics.scl.compiler.common.datatypes.Constructor;
+import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
import org.simantics.scl.compiler.common.names.Name;
+import org.simantics.scl.compiler.constants.Constant;
import org.simantics.scl.compiler.constants.JavaTypeInstanceConstructor;
import org.simantics.scl.compiler.constants.SCLConstructor;
import org.simantics.scl.compiler.constants.StringConstant;
import org.simantics.scl.compiler.constants.generic.ClassRef;
import org.simantics.scl.compiler.constants.generic.ConvertToListFilter;
import org.simantics.scl.compiler.constants.generic.MethodRef;
+import org.simantics.scl.compiler.constants.generic.MethodRef.FieldRef;
import org.simantics.scl.compiler.constants.generic.OutputFilter;
import org.simantics.scl.compiler.constants.generic.ParameterStackItem;
import org.simantics.scl.compiler.constants.generic.Pop2OutputFilter;
import org.simantics.scl.compiler.constants.generic.PopOutputFilter;
import org.simantics.scl.compiler.constants.generic.StackItem;
import org.simantics.scl.compiler.constants.generic.ThreadLocalStackItem;
+import org.simantics.scl.compiler.constants.singletons.SafeCoerce;
import org.simantics.scl.compiler.elaboration.contexts.TranslationContext;
import org.simantics.scl.compiler.elaboration.contexts.TypeTranslationContext;
import org.simantics.scl.compiler.elaboration.errors.NotPatternException;
import org.simantics.scl.compiler.elaboration.expressions.EIntegerLiteral;
import org.simantics.scl.compiler.elaboration.expressions.EListLiteral;
import org.simantics.scl.compiler.elaboration.expressions.ELiteral;
+import org.simantics.scl.compiler.elaboration.expressions.EPreCHRRulesetConstructor;
import org.simantics.scl.compiler.elaboration.expressions.EVar;
import org.simantics.scl.compiler.elaboration.expressions.Expression;
import org.simantics.scl.compiler.elaboration.expressions.Variable;
import org.simantics.scl.compiler.elaboration.java.JavaMethodDeclaration;
import org.simantics.scl.compiler.elaboration.macros.StandardMacroRule;
import org.simantics.scl.compiler.elaboration.modules.DeprecatedProperty;
+import org.simantics.scl.compiler.elaboration.modules.DerivedProperty;
import org.simantics.scl.compiler.elaboration.modules.InlineProperty;
import org.simantics.scl.compiler.elaboration.modules.MethodImplementation;
import org.simantics.scl.compiler.elaboration.modules.PrivateProperty;
import org.simantics.scl.compiler.elaboration.modules.TypeClass;
import org.simantics.scl.compiler.elaboration.modules.TypeClassInstance;
import org.simantics.scl.compiler.elaboration.modules.TypeClassMethod;
+import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor;
import org.simantics.scl.compiler.elaboration.query.Query;
import org.simantics.scl.compiler.elaboration.query.pre.QPreGuard;
import org.simantics.scl.compiler.elaboration.relations.ConcreteRelation;
import org.simantics.scl.compiler.environment.Environment;
import org.simantics.scl.compiler.environment.EnvironmentFactory;
import org.simantics.scl.compiler.environment.Environments;
+import org.simantics.scl.compiler.errors.CompilationError;
import org.simantics.scl.compiler.errors.ErrorLog;
+import org.simantics.scl.compiler.errors.ErrorSeverity;
import org.simantics.scl.compiler.errors.Locations;
import org.simantics.scl.compiler.internal.codegen.effects.EffectConstructor;
import org.simantics.scl.compiler.internal.codegen.effects.ThreadLocalVariable;
import org.simantics.scl.compiler.internal.elaboration.profiling.BranchPointInjector;
import org.simantics.scl.compiler.internal.elaboration.utils.StronglyConnectedComponents;
import org.simantics.scl.compiler.internal.header.ModuleHeader;
+import org.simantics.scl.compiler.internal.parsing.Token;
import org.simantics.scl.compiler.internal.parsing.declarations.ConstructorAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DAnnotationAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DClassAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DMappingRelationAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DRelationAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DRuleAst;
+import org.simantics.scl.compiler.internal.parsing.declarations.DRulesetAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DTypeAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst;
import org.simantics.scl.compiler.internal.parsing.declarations.DValueTypeAst;
import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
+import org.simantics.scl.compiler.internal.parsing.parser.SCLTerminals;
import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDClassAst;
import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDInstanceAst;
import org.simantics.scl.compiler.internal.parsing.translation.RelationRepository;
import org.simantics.scl.compiler.internal.parsing.types.TypeAst;
import org.simantics.scl.compiler.module.ConcreteModule;
import org.simantics.scl.compiler.module.ImportDeclaration;
+import org.simantics.scl.compiler.module.InvalidModulePathException;
+import org.simantics.scl.compiler.module.ModuleUtils;
+import org.simantics.scl.compiler.module.debug.ModuleDebugInfo;
import org.simantics.scl.compiler.module.repository.ImportFailure;
import org.simantics.scl.compiler.module.repository.ImportFailureException;
+import org.simantics.scl.compiler.top.SCLCompilerConfiguration;
import org.simantics.scl.compiler.types.TCon;
import org.simantics.scl.compiler.types.TForAll;
import org.simantics.scl.compiler.types.TFun;
this.errorLog = compilationContext.errorLog;
this.moduleName = moduleName;
this.moduleHeader = moduleHeader;
- importsAst = processRelativeImports(importsAst);
+ if(moduleName != null)
+ importsAst = processRelativeImports(compilationContext.errorLog, moduleName, importsAst);
this.importsAst = importsAst;
this.jrvFactory = jrvFactory;
this.javaReferenceValidator = moduleHeader == null || moduleHeader.classLoader == null
module = new ConcreteModule(moduleName);
compilationContext.module = module;
+ compilationContext.moduleRepository = localEnvironmentFactory.getModuleRepository();
+ if(moduleHeader != null) {
+ if(moduleHeader.defaultLocalName != null)
+ module.setDefaultLocalName(moduleHeader.defaultLocalName);
+ if(moduleHeader.deprecated != null)
+ module.setDeprecation(moduleHeader.deprecated);
+ }
try {
if(timer != null)
timer.suspendTimer();
importedEnvironment = localEnvironmentFactory.createEnvironment(
+ compilationContext,
importsAst.toArray(new ImportDeclaration[importsAst.size()]));
if(timer != null)
timer.continueTimer();
compilationContext.environment = new EnvironmentOfModule(importedEnvironment, module);
} catch (ImportFailureException e) {
for(ImportFailure failure : e.failures)
- errorLog.log(failure.location, failure.toString());
+ errorLog.log(new CompilationError(failure.location, failure.toString(), ErrorSeverity.IMPORT_ERROR));
return;
}
for(ImportDeclaration importAst : importsAst)
compilationContext.namingPolicy = new JavaNamingPolicy(moduleName);
}
- private ArrayList<ImportDeclaration> processRelativeImports(ArrayList<ImportDeclaration> relativeImports) {
+ public static ArrayList<ImportDeclaration> processRelativeImports(ErrorLog errorLog, String moduleName, ArrayList<ImportDeclaration> relativeImports) {
ArrayList<ImportDeclaration> absoluteImports = new ArrayList<ImportDeclaration>(relativeImports.size());
for(ImportDeclaration relativeImport : relativeImports) {
if(relativeImport.moduleName.startsWith(".")) {
- String absoluteModuleName = convertRelativeModulePath(relativeImport.location, relativeImport.moduleName);
- if(absoluteModuleName != null) {
+ try {
+ String absoluteModuleName = ModuleUtils.resolveAbsolutePath(moduleName, relativeImport.moduleName);
ImportDeclaration absoluteImport = new ImportDeclaration(
+ relativeImport.location,
absoluteModuleName, relativeImport.localName,
relativeImport.reexport, relativeImport.spec);
- absoluteImport.location = relativeImport.location;
absoluteImports.add(absoluteImport);
- }
+ } catch (InvalidModulePathException e) {
+ if(errorLog != null)
+ errorLog.log(relativeImport.location, e.getMessage());
+ }
}
else
absoluteImports.add(relativeImport);
return absoluteImports;
}
- private String convertRelativeModulePath(long location, String relativeModuleName) {
- String originalRelativeModuleName = relativeModuleName;
- int p = moduleName.lastIndexOf('/');
- String parentPackage = p < 0 ? "" : moduleName.substring(0, p);
- while(relativeModuleName.startsWith(".")) {
- if(relativeModuleName.startsWith("./")) {
- relativeModuleName = relativeModuleName.substring(2);
- }
- else if(relativeModuleName.startsWith("../")) {
- relativeModuleName = relativeModuleName.substring(3);
- if(parentPackage.isEmpty()) {
- errorLog.log(location, "Couldn't resolve the relative module name " + originalRelativeModuleName + " when the current module name is " + moduleName + ".");
- return null;
- }
- p = parentPackage.lastIndexOf('/');
- parentPackage = p < 0 ? "" : parentPackage.substring(0, p);
- }
- else {
- errorLog.log(location, "Couldn't resolve the relative module name " + originalRelativeModuleName + ". It has an invalid syntax.");
- return null;
- }
- }
- return parentPackage + "/" + relativeModuleName;
- }
-
public void addTypesToEnvironment(
ArrayList<DDataAst> dataTypesAst,
ArrayList<DTypeAst> typeAliasesAst,
- ArrayList<DEffectAst> effectsAst) {
+ ArrayList<DEffectAst> effectsAst,
+ ArrayList<DRulesetAst> rulesetsAst) {
for(DDataAst dataType : dataTypesAst) {
dataType.parameterKinds = new Kind[dataType.parameters.length];
Kind constructorKind = Kinds.STAR;
NameExistenceChecks.checkIfTypeExists(errorLog,
dataType.location, importedEnvironment, dataType.name);
- if(module.addTypeDescriptor(dataType.name, typeConstructor))
- errorLog.log(dataType.location, "Type "+dataType.name+" has already been defined in this module.");
+ addTypeDescriptor(dataType.location, dataType.name, typeConstructor);
dataType.typeConstructor = typeConstructor;
}
TypeAlias alias = new TypeAlias(Types.con(moduleName, typeAlias.name), typeAlias.parameters.length);
NameExistenceChecks.checkIfTypeExists(errorLog,
typeAlias.location, importedEnvironment, typeAlias.name);
- if(module.addTypeDescriptor(typeAlias.name, alias)) {
- errorLog.log(typeAlias.location, "Type alias "+typeAlias.name+" has already been defined in this module.");
- }
+ addTypeDescriptor(typeAlias.location, typeAlias.name, alias);
}
for(DEffectAst effect : effectsAst) {
TypeDesc.forClass(effect.threadLocalType)
));
if(module.addEffectConstructor(effect.name, effectConstructor))
- errorLog.log(effect.location, "Type "+effect.name+" has already been defined in this module.");
- }
+ errorLog.log(effect.location, "Effect "+effect.name+" has already been defined in this module.");
+ }
+ for(DRulesetAst ruleset : rulesetsAst) {
+ ruleset.type = Types.con(moduleName, ruleset.name);
+ ruleset.className = compilationContext.namingPolicy.getDataTypeClassName(ruleset.name);
+ StandardTypeConstructor typeConstructor = new StandardTypeConstructor(ruleset.type, Kinds.STAR,
+ TypeDesc.forClass(ruleset.className), ruleset.documentation == null ? null : ruleset.documentation.documentation);
+ typeConstructor.external = true;
+ addTypeDescriptor(ruleset.location, ruleset.name, typeConstructor);
+ }
javaTypeTranslator = new JavaTypeTranslator(compilationContext.environment);
compilationContext.javaTypeTranslator = javaTypeTranslator;
}
+
+ private void addTypeDescriptor(long location, String name, TypeDescriptor typeDescriptor) {
+ if(module.addTypeDescriptor(name, typeDescriptor))
+ errorLog.log(location, "Type "+name+" has already been defined in this module.");
+ }
private static final int[] EMPTY_INT_ARRAY = new int[0];
}
public void processDataTypes(ArrayList<DDataAst> dataTypesAst) {
+ ArrayList<Runnable> fieldAccessorGenerators = new ArrayList<Runnable>();
for(DDataAst dataTypeAst : dataTypesAst) {
TypeTranslationContext context = createTypeTranslationContext();
TVar[] typeParameters = new TVar[dataTypeAst.parameters.length];
dataTypes.add(dataType);
for(int j=0;j<constructors.length;++j) {
ConstructorAst constructor = dataTypeAst.constructors[j];
- String name = constructor.name;
+ String name = constructor.name.text;
Type[] parameterTypes = new Type[constructor.parameters.length];
for(int i=constructor.parameters.length-1;i>=0;--i)
parameterTypes[i] = context.toType(constructor.parameters[i]);
constructors[j].fieldNames = fieldNames;
constructors[j].recordFieldNames = constructor.fieldNames;
}
+ if(constructors.length == 1) {
+ Constructor constructor = constructors[0];
+ if(constructor.recordFieldNames != null) {
+ fieldAccessorGenerators.add(new Runnable() {
+ @Override
+ public void run() {
+ Type in = Types.apply(dataType.name, dataType.parameters);
+ for(int i=0;i<constructor.recordFieldNames.length;++i) {
+ Type out = constructor.parameterTypes[i];
+ Constant accessor;
+ if(trivialDataType)
+ accessor = new SafeCoerce(dataType.parameters, in, out);
+ else
+ accessor = new CallJava(dataType.parameters, Types.NO_EFFECTS, out,
+ new Type[] {in}, new StackItem[] {new ParameterStackItem(0, in)},
+ new FieldRef(constructor.javaName, constructor.fieldNames != null ? constructor.fieldNames[i] : "c" + i,
+ javaTypeTranslator.toTypeDesc(out)),
+ null);
+ module.addFieldAccessor(constructor.recordFieldNames[i], accessor);
+ }
+ }
+ });
+ }
+ }
}
+
+ for(Runnable fieldAccessorGenerator : fieldAccessorGenerators)
+ fieldAccessorGenerator.run();
}
public void processTypeClasses(ArrayList<ProcessedDClassAst> typeClassesAst) {
method.setDefaultImplementation(Name.create(moduleName, fullName));
valueDefinitionsAst.addDefinitions(fullName, defs);
- /*valueDefinitionsAst.addAnnotation(fullName, new DAnnotationAst(new EVar("@private"),
- Collections.<Expression>emptyList()));*/
- supplementedTypeAnnotations.add(new SupplementedValueType(defs.get(0).location, fullName, method.getType()));
+ supplementedTypeAnnotations.add(new SupplementedValueType(defs.get(0).location, fullName, method.getType()));
+ valueDefinitionsAst.setDerived(fullName);
}
module.addTypeClass(classAst.name, typeClass);
String fullName = instancePrefix + valueName;
long loc = valueDefs.getDefinition(valueName).get(0).location;
valueDefinitionsAst.addFrom(valueDefs, valueName, fullName);
+ valueDefinitionsAst.setDerived(fullName);
/*valueDefinitionsAst.addAnnotation(fullName, new DAnnotationAst(new EVar("@private"),
Collections.<Expression>emptyList()));*/
TypeClassMethod method = typeClass.methods.get(valueName);
type);
if(callJava != null) {
NameExistenceChecks.checkIfValueExists(errorLog, javaMethod.location,
- importedEnvironment, name);
+ importedEnvironment, module, name);
SCLValue value = module.addValue(name, callJava);
value.definitionLocation = javaMethod.methodName.location;
if(isPrivate)
}
}
+ public void processRulesets(ArrayList<DRulesetAst> rulesetsAst) {
+ for(DRulesetAst ruleset : rulesetsAst) {
+ String constructorName = "create" + ruleset.name;
+ supplementedTypeAnnotations.add(new SupplementedValueType(ruleset.location, constructorName, Types.functionE(Types.PUNIT, Types.PROC, ruleset.type)));
+ try {
+ valueDefinitionsAst.add(new DValueAst(new EVar(constructorName), new EPreCHRRulesetConstructor(ruleset)));
+ } catch (NotPatternException e) {
+ throw new InternalCompilerError(ruleset.location, e);
+ }
+ }
+ }
+
/**
* Convert a java class method into a {@link CallJava} instance.
* Compilation errors are logged for failures in finding the named class or in accessing the method.
final THashMap<SectionName, Query[]> sections = new THashMap<SectionName, Query[]>();
- final TranslationContext context = createTranslationContext();
+ final TranslationContext context = createTranslationContext(ruleName);
if(length > 0) {
THashMap<String, Variable> variables = context.getVariables();
for(TransformationRule extendsRule : extendsRules) {
int constructorTag = 0;
for(Constructor constructor : dataType.constructors) {
SCLValue value = new SCLValue(constructor.name);
+ value.definitionLocation = constructor.loc;
SCLConstructor sclConstructor =
new SCLConstructor(
constructor.name.name,
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());
NameExistenceChecks.checkIfValueExists(errorLog, constructor.loc,
- importedEnvironment, constructor.name.name);
+ importedEnvironment, module, constructor.name.name);
if(module.addValue(value)) {
errorLog.log(constructor.loc,
"Value " + constructor.name.name + " is already defined.");
SCLValue value = method.createValue();
value.definitionLocation = method.location;
NameExistenceChecks.checkIfValueExists(errorLog, Locations.NO_LOCATION,
- importedEnvironment, value.getName().name);
+ importedEnvironment, module, value.getName().name);
if(module.addValue(value)) {
String name = method.getName();
long location = valueDefinitionsAst.getLocation(name);
NameExistenceChecks.checkIfValueExists(errorLog, location,
- importedEnvironment, value.getName().name);
+ importedEnvironment, module, value.getName().name);
value.definitionLocation = location;
if(module.addValue(value))
errorLog.log(location, "Value " + name + " is already defined.");
+ if(valueDefinitionsAst.isDerived(name))
+ value.addProperty(DerivedProperty.INSTANCE);
}
for(DValueTypeAst valueTypeAst : typeAnnotationsAst)
for(EVar name : valueTypeAst.names) {
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);
+ if(defs.size() != 1 || !(defs.get(0).value instanceof EPreCHRRulesetConstructor))
+ continue;
try {
SCLValue value = module.getValue(name);
- TranslationContext context = createTranslationContext();
+ TranslationContext context = createTranslationContext(name);
+ Expression expression = context.translateCases2(defs);
+ value.setExpression(expression);
+
+ if(exportMap != null && exportMap.remove(name) == null)
+ value.addProperty(PrivateProperty.INSTANCE);
+ } catch(RuntimeException e) {
+ errorLog.setExceptionPosition(defs.get(0).location);
+ throw e;
+ }
+ }
+ for(String name : valueDefinitionsAst.getValueNames()) {
+ ArrayList<DValueAst> defs = valueDefinitionsAst.getDefinition(name);
+ if(defs.size() == 1 && defs.get(0).value instanceof EPreCHRRulesetConstructor)
+ continue;
+ try {
+ SCLValue value = module.getValue(name);
+ TranslationContext context = createTranslationContext(name);
Expression expression = context.translateCases2(defs);
value.setExpression(expression);
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) {
DRelationAst definition = definitions.get(0);
ConcreteRelation relation = (ConcreteRelation)module.getRelation(name);
relation.location = definition.location;
- TranslationContext context = createTranslationContext();
+ TranslationContext context = createTranslationContext(name);
definition.translateTo(context, relation);
}
}
- private TranslationContext createTranslationContext() {
- return new TranslationContext(compilationContext, null);
+ private TranslationContext createTranslationContext(String definitionName) {
+ return new TranslationContext(compilationContext, null, definitionName);
}
private void handleAnnotation(SCLValue value, ArrayList<DValueAst> defs, DAnnotationAst annotation) {
}
}
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")) {
branchPoints.put(valueName, injector.getAndClearBranchPoints());
}
}
+
+ public void collectDebugInfo() {
+ module.moduleDebugInfo = compilationContext.moduleDebugInfo = new ModuleDebugInfo();
+ }
}