X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Finternal%2Fderiving%2FJsonDeriver.java;fp=bundles%2Forg.simantics.scl.compiler%2Fsrc%2Forg%2Fsimantics%2Fscl%2Fcompiler%2Finternal%2Fderiving%2FJsonDeriver.java;h=24f8b316230547bab65c614a6359587e28d1a14f;hb=22b86b38b00d6e168a5872e70113efd5fc1d81b6;hp=0000000000000000000000000000000000000000;hpb=66b0fd2ee69d84d3107f109679b6fd1866f8f3fc;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/JsonDeriver.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/JsonDeriver.java new file mode 100644 index 000000000..24f8b3162 --- /dev/null +++ b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/deriving/JsonDeriver.java @@ -0,0 +1,218 @@ +package org.simantics.scl.compiler.internal.deriving; + +import java.util.ArrayList; + +import org.simantics.scl.compiler.common.datatypes.Constructor; +import org.simantics.scl.compiler.common.names.Names; +import org.simantics.scl.compiler.constants.StringConstant; +import org.simantics.scl.compiler.elaboration.errors.NotPatternException; +import org.simantics.scl.compiler.elaboration.expressions.EApply; +import org.simantics.scl.compiler.elaboration.expressions.EConstant; +import org.simantics.scl.compiler.elaboration.expressions.EListLiteral; +import org.simantics.scl.compiler.elaboration.expressions.ELiteral; +import org.simantics.scl.compiler.elaboration.expressions.ERecord; +import org.simantics.scl.compiler.elaboration.expressions.EVar; +import org.simantics.scl.compiler.elaboration.expressions.Expression; +import org.simantics.scl.compiler.elaboration.expressions.records.FieldAssignment; +import org.simantics.scl.compiler.elaboration.modules.SCLValue; +import org.simantics.scl.compiler.elaboration.modules.TypeAlias; +import org.simantics.scl.compiler.elaboration.modules.TypeConstructor; +import org.simantics.scl.compiler.elaboration.modules.TypeDescriptor; +import org.simantics.scl.compiler.environment.AmbiguousNameException; +import org.simantics.scl.compiler.environment.Environment; +import org.simantics.scl.compiler.environment.Environments; +import org.simantics.scl.compiler.errors.ErrorLog; +import org.simantics.scl.compiler.internal.parsing.declarations.DDerivingInstanceAst; +import org.simantics.scl.compiler.internal.parsing.declarations.DInstanceAst; +import org.simantics.scl.compiler.internal.parsing.declarations.DValueAst; +import org.simantics.scl.compiler.internal.parsing.translation.ProcessedDInstanceAst; +import org.simantics.scl.compiler.internal.parsing.translation.ValueRepository; +import org.simantics.scl.compiler.internal.parsing.types.TVarAst; +import org.simantics.scl.compiler.types.TApply; +import org.simantics.scl.compiler.types.TCon; +import org.simantics.scl.compiler.types.Type; +import org.simantics.scl.compiler.types.Types; + +class JsonDeriver implements InstanceDeriver { + + @Override + public void derive( + ErrorLog errorLog, + Environment environment, + ArrayList instancesAst, + DDerivingInstanceAst der) { + // Analyze + if(der.types.length != 1) { + errorLog.log(der.location, "Invalid number of parameters to " + der.name); + return; + } + TVarAst headType = DerivingUtils.getHeadType(der.types[0]); + if(headType == null) { + errorLog.log(der.types[0].location, "Cannot derive Json instance for the type " + headType + "."); + return; + } + TCon con; + try { + con = Environments.getTypeDescriptorName(environment, headType.name); + } catch (AmbiguousNameException e1) { + errorLog.log(headType.location, e1.getMessage()); + return; + } + if(con == null) { + errorLog.log(headType.location, "Couldn't resolve " + headType.name); + return; + } + TypeDescriptor tdesc = environment.getTypeDescriptor(con); + if(tdesc == null) { + errorLog.log(headType.location, "Didn't find type constructor for " + headType.name); + return; + } + if(tdesc instanceof TypeAlias) { + errorLog.log(headType.location, "Cannot derive instance for a type alias."); + return; + } + TypeConstructor tcon = (TypeConstructor)tdesc; + if(tcon.isOpen) { + errorLog.log(headType.location, "Cannot derive instance for open data types."); + return; + } + + if(tcon.constructors.length != 1) { + errorLog.log(headType.location, "Data must have exactly one constructor for deriving to work."); + return; + } + Constructor constructor = tcon.constructors[0]; + if(constructor.recordFieldNames == null) { + errorLog.log(headType.location, "Data must have a record constructor for deriving to work."); + return; + } + + DInstanceAst instanceAst = new DInstanceAst(der.location, der.context, der.name, der.types); + ValueRepository valueDefs = new ValueRepository(); + + SCLValue fromJson = environment.getValue(Names.Json_fromJson); + SCLValue toJson = environment.getValue(Names.Json_toJson); + SCLValue lookupJsonField = environment.getValue(Names.Json_lookupJsonField); + SCLValue JsonObject = environment.getValue(Names.Json_JsonObject); + SCLValue JsonField = environment.getValue(Names.Json_JsonField); + + SCLValue Just = environment.getValue(Names.Builtin_Just); + SCLValue fromJust = environment.getValue(Names.Prelude_fromJust); + SCLValue map = environment.getValue(Names.Prelude_map); + SCLValue filterJust = environment.getValue(Names.Prelude_filterJust); + SCLValue dot = environment.getValue(Names.Prelude_dot); + + // Collect all relevant information about the constructor + String constructorName = constructor.name.name; + int fieldCount = constructor.parameterTypes.length; + String[] fieldNames = constructor.recordFieldNames; + boolean[] isOptional = new boolean[fieldCount]; + boolean hasAtLeastOneOptional = false; + for(int i=0;i