]> gerrit.simantics Code Review - simantics/platform.git/commitdiff
SCL compiler generates line numbers to bytecode 34/1534/3
authorHannu Niemistö <hannu.niemisto@semantum.fi>
Thu, 8 Mar 2018 06:18:56 +0000 (08:18 +0200)
committerTuukka Lehtonen <tuukka.lehtonen@semantum.fi>
Thu, 8 Mar 2018 12:31:04 +0000 (14:31 +0200)
refs #6922

Change-Id: I2219d6dc74ae815cdea7d3f6daf3a736be5f1781

40 files changed:
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CodeGeneration.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/CompilationContext.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/compilation/SCLCompiler.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/SCLConstant.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/constants/singletons/ThrowFunction.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/CHRRuleset.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/AccessFactOp.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/IterateConstraintOp.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/MatchOp.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PlanContext.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/chr/plan/PostCommitOp.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EIf.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/ELet.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/EMatch.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/Expression.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/expressions/GuardedExpressionGroup.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/elaboration/java/Builtins.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/continuations/Cont.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSABlock.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAExit.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAFunction.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAModule.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/SSAStatement.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/If.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Jump.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Switch.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/exits/Throw2.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/ssa/statements/LetApply.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/utils/MethodBuilderBase.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/writer/CodeWriter.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/codegen/writer/ModuleWriter.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/matching/PatternMatchingCompiler.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/elaboration/matching2/PatternMatchingCompiler2.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/utils/LineLocator.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/utils/LineLocators.java [new file with mode: 0644]
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/StringModuleSource.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/source/TextualModuleSource.java
bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/top/ExpressionEvaluator.java
bundles/org.simantics.tests.modelled.ui/src/org/simantics/tests/modelled/ui/STSTestEditorInput.java

index 68c5847082d96e7f1db80a1a83f9d4d2d9bcdbb7..082fa2f6dc553d1b36e2b64c6152329f46b87725 100644 (file)
@@ -108,7 +108,7 @@ public class CodeGeneration {
     }
     
     public void convertToSSA() {
-        ModuleWriter mw = new ModuleWriter(compilationContext.namingPolicy.getModuleClassName());
+        ModuleWriter mw = new ModuleWriter(compilationContext.namingPolicy.getModuleClassName(), compilationContext.lineLocator);
         for(SCLValue value : module.getValues()) {
             //System.out.println(value.getName().name + " :: " + value.getType());
             Expression expression = value.getExpression();
@@ -172,7 +172,7 @@ public class CodeGeneration {
                 IVal[] parameterVals = w.getParameters();
                 for(int i=0;i<decomposed.parameters.length;++i)
                     decomposed.parameters[i].setVal(parameterVals[i]);
-                w.return_(decomposed.body.toVal(compilationContext, w));            
+                w.return_(expression.location, decomposed.body.toVal(compilationContext, w));            
             } catch(RuntimeException e) {
                 long location = value.getExpression().location;
                 if(location == Locations.NO_LOCATION)
index bd6546dacfe05abc4bd52643a203087a90b5b48b..0fe0250d369f4c4311b2badb594f0a26adf073af 100644 (file)
@@ -12,6 +12,7 @@ import org.simantics.scl.compiler.errors.Locations;
 import org.simantics.scl.compiler.internal.codegen.types.JavaTypeTranslator;
 import org.simantics.scl.compiler.internal.codegen.utils.JavaNamingPolicy;
 import org.simantics.scl.compiler.internal.header.ModuleHeader;
+import org.simantics.scl.compiler.internal.parsing.utils.LineLocator;
 import org.simantics.scl.compiler.module.ConcreteModule;
 import org.simantics.scl.compiler.module.debug.ModuleDebugInfo;
 import org.simantics.scl.compiler.module.repository.ModuleRepository;
@@ -21,6 +22,7 @@ import gnu.trove.map.hash.THashMap;
 
 public class CompilationContext implements EnvironmentalContext {
     public final ErrorLog errorLog = new ErrorLog();
+    public LineLocator lineLocator;
     public ModuleRepository moduleRepository;
     public Environment environment;
     public JavaTypeTranslator javaTypeTranslator;
index 1c674ae4d573126570d8307b9bbf0fc6ff9ba31f..5e713f1f483c0150083ee4a19cdf7970d1f0828e 100644 (file)
@@ -1,18 +1,17 @@
 package org.simantics.scl.compiler.compilation;
 
-import java.io.IOException;
-import java.io.Reader;
+import java.io.StringReader;
 import java.util.ArrayList;
 import java.util.Map;
 
 import org.simantics.scl.compiler.environment.EnvironmentFactory;
 import org.simantics.scl.compiler.errors.ErrorLog;
 import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidatorFactory;
-import org.simantics.scl.compiler.internal.header.ModuleHeader;
 import org.simantics.scl.compiler.internal.parsing.declarations.DeclarationAst;
 import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorException;
 import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl;
 import org.simantics.scl.compiler.internal.parsing.parser.SCLParserOptions;
+import org.simantics.scl.compiler.internal.parsing.utils.LineLocators;
 import org.simantics.scl.compiler.module.ConcreteModule;
 import org.simantics.scl.compiler.module.options.ModuleCompilationOptions;
 import org.simantics.scl.compiler.top.ModuleInitializer;
@@ -39,10 +38,11 @@ public class SCLCompiler {
     }
 
     @SuppressWarnings("unchecked")
-    public void addSource(Reader sourceReader) {
+    public void addSource(String source) {
         if(SCLCompilerConfiguration.ENABLE_TIMING) initializeTiming();
         try {
-            SCLParserImpl parser = new SCLParserImpl(sourceReader);
+            compilationContext.lineLocator = LineLocators.createLineLocator(source);
+            SCLParserImpl parser = new SCLParserImpl(new StringReader(source));
             parser.setParserOptions(SCLParserOptions.MODULE_DEFAULT);
             parser.setCompilationContext(compilationContext);
             if(!parser.isEmpty())
@@ -52,12 +52,6 @@ public class SCLCompiler {
             compilationContext.errorLog.log(e.location, e.getMessage());
         } catch(Exception e) {
             compilationContext.errorLog.log(e);
-        } finally {
-            try {
-                sourceReader.close();
-            } catch (IOException e) {
-                e.printStackTrace();
-            }
         }
         if(SCLCompilerConfiguration.ENABLE_TIMING) phaseFinished("Parsing");
     }
index 9089ebb817209e1735ebcaf3dcfd7e39d65585b9..0fe09df8b8d5845400550d5ff3638a9ed8fca46c 100644 (file)
@@ -109,7 +109,7 @@ public class SCLConstant extends DelegateConstant implements Named {
         }
         else /*if(parameters.length < def.getArity())*/ {
             def.applyTypes(functionRef.getTypeParameters());
-            def.apply(parameters);
+            def.apply(apply.lineNumber, parameters);
                         
             def.setTarget(apply.getTarget());
             new LetFunctions(def).insertBefore(apply);
index 5a6f4068c00f926971fe8f59cd50c4d943e3d216..1788add7eba844b4fda8f2aaa95152dbb2789e33 100644 (file)
@@ -47,7 +47,7 @@ public class ThrowFunction extends FunctionValue {
         apply.getFunction().remove();
         apply.detachThisAndSuccessors();
         block.getExit().destroy();
-        block.setExit(new Throw2(apply.getParameters()[0]));
+        block.setExit(new Throw2(apply.lineNumber, apply.getParameters()[0]));
         context.markModified("inline-throw");
     }
 }
index 55bbcfe34f9c245968083ab39e374b9814fc8908..aa59d4c0239159b604d396be91710fb66d69cfda 100644 (file)
@@ -257,7 +257,7 @@ public class CHRRuleset extends Symbol {
                 PlanRealizer realizer = new PlanRealizer(cachedContext, this, runtimeRulesetVariable, implementationParameters[0], plan.ops);
                 realizer.nextOp(methodWriter);
                 if(methodWriter.isUnfinished())
-                    methodWriter.return_(BooleanConstant.TRUE);
+                    methodWriter.return_(rule.location, BooleanConstant.TRUE);
             }
         }
         if(!includes.isEmpty() || extensible) {
@@ -273,7 +273,7 @@ public class CHRRuleset extends Symbol {
                        methodWriter.apply(Locations.NO_LOCATION,
                                new JavaMethod(true, runtimeRulesetClassName, "register", Types.PROC, Types.UNIT, new Type[] {runtimeRulesetType, Types.CHRContext}),
                                object.getTarget(), methodWriter.getParameters()[0]);
-                methodWriter.return_(NoRepConstant.UNIT);
+                methodWriter.return_(location, NoRepConstant.UNIT);
             }
             {
                 CodeWriter methodWriter = object.createMethod(w.getModuleWriter(), TVar.EMPTY_ARRAY, Types.PROC, Types.UNIT, new Type[] {Types.CHRContext});
@@ -287,7 +287,7 @@ public class CHRRuleset extends Symbol {
                        methodWriter.apply(Locations.NO_LOCATION,
                                new JavaMethod(true, runtimeRulesetClassName, "unregister", Types.PROC, Types.UNIT, new Type[] {runtimeRulesetType, Types.CHRContext}),
                                object.getTarget(), methodWriter.getParameters()[0]);
-                methodWriter.return_(NoRepConstant.UNIT);
+                methodWriter.return_(location, NoRepConstant.UNIT);
             }
         }
         if(initConstraint != null) {
index ab37d253a50dbcfdf709553a13230f9f1f89fe54..c0cb00184770119175520905e9a3837b0b1873b6 100644 (file)
@@ -45,6 +45,6 @@ public class AccessFactOp extends PlanOp {
         planContext.partnerFacts.add(new PartnerFact(true, activeId, constraint, inputVal, constraint.mayBeRemoved(), killAfterMatch, null, null, end == null ? null : end.getContinuation()));
         planContext.nextOp(w);
         if(end != null)
-            end.return_(BooleanConstant.FALSE);
+            end.return_(location, BooleanConstant.FALSE);
     }
 }
index 035ccd624a134f8942e3d19a8908fca2ddda75a5..ddaaebd68d3906313e3e12b81f3d2012f52a771a 100644 (file)
@@ -59,19 +59,19 @@ public class IterateConstraintOp extends PlanOp {
         for(int i=0;i<expressions.length;++i)
             if(((boundMask>>i)&1)==1)
                 parameters.add(expressions[i].toVal(context, w));
-        w.jump(bodyContinuation, w.apply(location,
+        w.jump(location, bodyContinuation, w.apply(location,
                 constraint.fetchFromIndex(context, boundMask), parameters.toArray(new IVal[parameters.size()])));
 
-        body.branchAwayIf(body.apply(location, NullCheck.INSTANCE.createSpecialization(constraint.factType), fact),
+        body.branchAwayIf(location, body.apply(location, NullCheck.INSTANCE.createSpecialization(constraint.factType), fact),
                 end.getContinuation());
         IVal id = body.apply(location, constraint.accessId, fact);
         for(PartnerFact partnerFact : planContext.partnerFacts)
             if(partnerFact.active && !passive) {
-                body.branchAwayUnless(body.apply(location, JavaComparisonOperation.ILESS, id, partnerFact.id),
+                body.branchAwayUnless(location, body.apply(location, JavaComparisonOperation.ILESS, id, partnerFact.id),
                         nextFact.getContinuation());
             }
             else if(partnerFact.constraint == constraint) {
-                body.branchAwayIf(body.apply(location, JavaComparisonOperation.IEQUAL, id, partnerFact.id),
+                body.branchAwayIf(location, body.apply(location, JavaComparisonOperation.IEQUAL, id, partnerFact.id),
                         nextFact.getContinuation());
             }
 
@@ -82,8 +82,8 @@ public class IterateConstraintOp extends PlanOp {
         planContext.partnerFacts.add(new PartnerFact(false, id, constraint, fact, constraint.mayBeRemoved(), killAfterMatch, nextElement, bodyContinuation, end.getContinuation()));
         planContext.nextOp(body);
         if(body.isUnfinished()) 
-            body.jump(nextFact.getContinuation());
-        nextFact.jump(bodyContinuation, nextFact.apply(location, nextElement, fact));
+            body.jump(location, nextFact.getContinuation());
+        nextFact.jump(location, bodyContinuation, nextFact.apply(location, nextElement, fact));
 
         w.continueAs(end);
     }   
index cde56694999a1cff36708b866add77e1d790f09c..4a99ac0d9a1f4ea1d2aa042c46ef535b9c1af442 100644 (file)
@@ -35,11 +35,11 @@ public class MatchOp extends PlanOp {
         ArrayList<Row2> rows = new ArrayList<Row2>(1);
         rows.add(new Row2(new Expression[] {pattern}, body.getContinuation()));
 
-        PatternMatchingCompiler2.split(w, context, scrutineeVals, end.getContinuation(), rows);
+        PatternMatchingCompiler2.split(location, w, context, scrutineeVals, end.getContinuation(), rows);
         
         planContext.nextOp(body);
         if(body.isUnfinished())
-            body.jump(end.getContinuation());
+            body.jump(location, end.getContinuation());
         
         w.continueAs(end);
     }
index 2a03c89435e7de85ab9a8ac75a7346b60ca0a45c..62bcfc9581fd9650c4d869c4c0a7b759e423de2a 100644 (file)
@@ -54,15 +54,15 @@ public abstract class PlanContext {
         ICont bodyContinuation = body.getContinuation();
         CodeWriter end = w.createBlock();
                 
-        w.jump(body.getContinuation(), IntegerConstant.ZERO);
+        w.jump(location, body.getContinuation(), IntegerConstant.ZERO);
         
         IVal index = body.getParameters()[0];
-        body.branchAwayIf(body.apply(location, JavaComparisonOperation.IEQUAL, index, listLength),
+        body.branchAwayIf(location, body.apply(location, JavaComparisonOperation.IEQUAL, index, listLength),
                 end.getContinuation());
         variable.setVal(body.apply(location, ListElement.INSTANCE.createSpecialization(componentType), listValue, index));
         nextOp(body);
         if(body.isUnfinished())
-            body.jump(bodyContinuation, body.apply(location, IncreaseByOne.INSTANCE, index));
+            body.jump(location, bodyContinuation, body.apply(location, IncreaseByOne.INSTANCE, index));
         
         w.continueAs(end);
     }
@@ -72,7 +72,7 @@ public abstract class PlanContext {
 
         CodeWriter end = w.createBlock();
         CodeWriter body = w.createBlock(componentType);
-        w.switch_(maybeValue, new Branch[] {
+        w.switch_(location, maybeValue, new Branch[] {
                 new Branch(JustConstant.INSTANCE, body.getContinuation()),
                 new Branch(null, end.getContinuation())
         });
@@ -80,17 +80,17 @@ public abstract class PlanContext {
         variable.setVal(body.getParameters()[0]);
         nextOp(body);
         if(body.isUnfinished())
-            body.jump(end.getContinuation());
+            body.jump(location, end.getContinuation());
         
         w.continueAs(end);
     }
 
     public void check(long location, CodeWriter w, IVal booleanValue) {
         CodeWriter end = w.createBlock();
-        w.branchAwayUnless(booleanValue, end.getContinuation());
+        w.branchAwayUnless(location, booleanValue, end.getContinuation());
         nextOp(w);
         if(w.isUnfinished())
-            w.jump(end.getContinuation());
+            w.jump(location, end.getContinuation());
         w.continueAs(end);
     }
 
@@ -105,16 +105,16 @@ public abstract class PlanContext {
 
         CodeWriter end = w.createBlock();
         CodeWriter body = w.createBlock(componentType);
-        w.switch_(maybeValue, new Branch[] {
+        w.switch_(location, maybeValue, new Branch[] {
                 new Branch(JustConstant.INSTANCE, body.getContinuation()),
                 new Branch(null, end.getContinuation())
         });
-        body.branchAwayUnless(body.apply(location,
+        body.branchAwayUnless(location, body.apply(location,
                 EqualsFunction.INSTANCE.createSpecialization(componentType),
                 value, body.getParameters()[0]), end.getContinuation());
         nextOp(body);
         if(body.isUnfinished())
-            body.jump(end.getContinuation());
+            body.jump(location, end.getContinuation());
         
         w.continueAs(end);
     }
index a43e97d4cfcc1094933e56f93511c1016552c299..5902f958879e30613410c873a301ba3381aeed2b 100644 (file)
@@ -32,23 +32,23 @@ public class PostCommitOp extends PlanOp {
         for(PartnerFact activeFact : planContext.partnerFacts) {
             if(activeFact.killAfterMatch) {
                 if(activeFact.nextFact == null)
-                    w.jump(activeFact.finishCont);
+                    w.jump(location, activeFact.finishCont);
                 else {
                     CodeWriter iterateAlive = w.createBlock(activeFact.constraint.factType);
-                    w.jump(iterateAlive.getContinuation(), w.apply(location, activeFact.nextFact, activeFact.factVar));
+                    w.jump(location, iterateAlive.getContinuation(), w.apply(location, activeFact.nextFact, activeFact.factVar));
                     iterateUntilLiveFactFound(iterateAlive, activeFact);
                 }
                 break;
             }
             else if(activeFact.mayBeRemoved) {
                 if(activeFact.nextFact == null) {
-                    w.branchAwayUnless(activeFact.isAlive(location, w), activeFact.finishCont);
+                    w.branchAwayUnless(location, activeFact.isAlive(location, w), activeFact.finishCont);
                 }
                 else {
                     CodeWriter failure = w.createBlock();
                     CodeWriter iterateAlive = w.createBlock(activeFact.constraint.factType);
-                    w.branchAwayUnless(activeFact.isAlive(location, w), failure.getContinuation());
-                    failure.jump(iterateAlive.getContinuation(), failure.apply(location, activeFact.nextFact, activeFact.factVar));
+                    w.branchAwayUnless(location, activeFact.isAlive(location, w), failure.getContinuation());
+                    failure.jump(location, iterateAlive.getContinuation(), failure.apply(location, activeFact.nextFact, activeFact.factVar));
                     iterateUntilLiveFactFound(iterateAlive, activeFact);     
                 }
             }
@@ -61,10 +61,10 @@ public class PostCommitOp extends PlanOp {
         CHRConstraint constraint = activeFact.constraint;
         IVal fact = w.getParameters()[0];
         CodeWriter dead = w.createBlock();
-        w.branchAwayIf(w.apply(location, NullCheck.INSTANCE.createSpecialization(constraint.factType), fact), activeFact.finishCont);
-        w.branchAwayUnless(activeFact.isAlive(location, w, fact), dead.getContinuation());
-        w.jump(activeFact.continueCont, fact);
-        dead.jump(initialContinuation, dead.apply(location, activeFact.nextFact, fact));
+        w.branchAwayIf(location, w.apply(location, NullCheck.INSTANCE.createSpecialization(constraint.factType), fact), activeFact.finishCont);
+        w.branchAwayUnless(location, activeFact.isAlive(location, w, fact), dead.getContinuation());
+        w.jump(location, activeFact.continueCont, fact);
+        dead.jump(location, initialContinuation, dead.apply(location, activeFact.nextFact, fact));
     }
 
 }
index fe6216fe153c3bb8fec3da0e83c86940aa8a9269..149c52f500235d5f732aa4a12f744b3d75851bc7 100644 (file)
@@ -47,16 +47,16 @@ public class EIf extends Expression {
         CodeWriter thenBlock = w.createBlock();
         if(else_ != null) {
             CodeWriter elseBlock = w.createBlock();        
-            w.if_(conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation());
+            w.if_(location, conditionVal, thenBlock.getContinuation(), elseBlock.getContinuation());
                 
             IVal elseVal = else_.toVal(context, elseBlock);
-            elseBlock.jump(joinPoint.getContinuation(), elseVal);
+            elseBlock.jump(location, joinPoint.getContinuation(), elseVal);
         }
         else {
-            w.if_(conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation());
+            w.if_(location, conditionVal, thenBlock.getContinuation(), joinPoint.getContinuation());
         }
         IVal thenVal = then_.toVal(context, thenBlock);
-        thenBlock.jump(joinPoint.getContinuation(), thenVal);
+        thenBlock.jump(location, joinPoint.getContinuation(), thenVal);
         w.continueAs(joinPoint);
         
         return w.getParameters()[0];
index 23c5b0be282d7fbd4a0a840cd00dd6b43fb4cce5..811877aa0b618c6052933cfece5f05163ddff3d9 100644 (file)
@@ -154,7 +154,7 @@ public class ELet extends Expression {
             IVal[] parameters = newW.getParameters();
             for(int j=0;j<parameters.length;++j)
                 decomposed.parameters[j].setVal(parameters[j]);
-            newW.return_(decomposed.body.toVal(context, newW));
+            newW.return_(assignments[i].value.location, decomposed.body.toVal(context, newW));
         }
         return in.toVal(context, w);
     }
index 279815ecfd1b19227483a7b363bc6e137af63303..494bcfb5d6bfc9d93aab0b50bfd2de29c233cbb7 100644 (file)
@@ -54,7 +54,7 @@ public class EMatch extends Expression {
 
         CodeWriter joinPoint = w.createBlock(getType());
         CodeWriter failurePoint = w.createBlock(); // TODO generate only one failurePoint per function
-        PatternMatchingCompiler.split(w, context, scrutineeVals, joinPoint.getContinuation(), failurePoint.getContinuation(), rows);
+        PatternMatchingCompiler.split(location, w, context, scrutineeVals, joinPoint.getContinuation(), failurePoint.getContinuation(), rows);
         failurePoint.throw_(location, Throw.MatchingException, "Matching failure at: " + toString());
         w.continueAs(joinPoint);
         return w.getParameters()[0];
index 3a2f845fe88191cb594022c5e0c49f60197b1db5..dcb38165e7665ae66bf6af53c458e277dc192700 100644 (file)
@@ -320,7 +320,7 @@ public abstract class Expression extends Symbol implements Typed {
         IVal functionVal = newW.getFunction().getTarget();
         for(int i=0;i<parameters.length;++i)
             decomposed.parameters[i].setVal(parameters[i]);
-        newW.return_(decomposed.body.toVal(context, newW));
+        newW.return_(decomposed.body.location, decomposed.body.toVal(context, newW));
         return functionVal;
     }
     
index 48283a887a2dc883ded12c0632faf800d434b097..402d6fab3247758ba525f9de7c0147af21bd39e3 100644 (file)
@@ -88,11 +88,11 @@ public class GuardedExpressionGroup extends Expression {
             
             for(Expression guard : expressions[i].guards) {
                 CodeWriter nextW = w.createBlock();
-                w.if_(guard.toVal(context, w), nextW.getContinuation(), failure);
+                w.if_(guard.location, guard.toVal(context, w), nextW.getContinuation(), failure);
                 w = nextW;
             }
             
-            w.jump(success, expressions[i].value.toVal(context, w));
+            w.jump(expressions[i].location, success, expressions[i].value.toVal(context, w));
         }
     }
     
index 083c3d58f132afb00f11cb79a5b1dd1ea22ee3e3..4846f75a13b2b605297807d11fe5c60a9fd800be 100644 (file)
@@ -231,7 +231,7 @@ public class Builtins extends ConcreteModule {
                     );
             block.addStatement(apply);
             
-            block.setExit(new Jump(runProcFunction.getReturnCont().createOccurrence(), 
+            block.setExit(new Jump(-1, runProcFunction.getReturnCont().createOccurrence(), 
                     x.createOccurrence()));
             
             runProcFunction.addBlock(block);
index 62d6680de9969bd1ae14e29e48226eebb7c1ac6e..504e37f49460194302be5d15ae496a26a7e3d21a 100644 (file)
@@ -68,7 +68,7 @@ public abstract class Cont implements ICont {
             proxyParameters[i] = new BoundVar(oldParameters[i].getType());
         SSABlock block = new SSABlock(proxyParameters);
         function.addBlock(block);
-        block.setExit(new Jump(createOccurrence(), 
+        block.setExit(new Jump(-1, createOccurrence(), 
                 ValRef.concat(ValRef.createOccurrences(newParameters), 
                         ValRef.createOccurrences(proxyParameters))));
         return block;
index 60e156a7f0a683dbac408cf2d9b8ba8d61bfa035..fba16bf8370817329234bc66fee160c09dd1f596 100644 (file)
@@ -443,7 +443,7 @@ public final class SSABlock extends Cont implements Printable, BoundVarBinder {
             for(BranchRef branch : sw.getBranches()) {
                 if(branch.constructor == function) {
                     sw.destroy();
-                    setExit(new Jump(branch.cont.getBinding().createOccurrence(), 
+                    setExit(new Jump(sw.lineNumber, branch.cont.getBinding().createOccurrence(), 
                             ValRef.copy(apply.getParameters())));
                     return true;
                 }
@@ -461,7 +461,7 @@ public final class SSABlock extends Cont implements Printable, BoundVarBinder {
                      *      [a]
                      */
                     sw.destroy();
-                    setExit(new Jump(branch.cont.getBinding().createOccurrence()));
+                    setExit(new Jump(sw.lineNumber, branch.cont.getBinding().createOccurrence()));
                 }
             }
         }
index ae9ad5725a436256b382fbd12853544286c06312..ab3c8c1d973f9d6383541b23d41c86ee7807681a 100644 (file)
@@ -22,7 +22,11 @@ import org.simantics.scl.compiler.types.Types;
 
 public abstract class SSAExit implements Printable {
     SSABlock parent;
-    public long location;
+    public final int lineNumber;
+    
+    public SSAExit(int lineNumber) {
+        this.lineNumber = lineNumber;
+    }
 
     public abstract void generateCode(MethodBuilder mb);
 
index 0a608a3d342adf6a9253fd400892475ce6b45131..b2db131a41f50d6f55765d300ebd6d7cf42e30d1 100644 (file)
@@ -279,7 +279,7 @@ public final class SSAFunction extends SSAClosure {
         for(SSABlock block = f.firstBlock; block != null; block = block.next)
             block.parent = this;
         lastBlock.next = f.firstBlock;
-        f.firstBlock.prev = lastBlock;        
+        f.firstBlock.prev = lastBlock;
         lastBlock = f.lastBlock;
         
         firstBlock.firstStatement = firstBlock.lastStatement = null;
@@ -287,7 +287,7 @@ public final class SSAFunction extends SSAClosure {
         effect = f.effect;
         BoundVar[] newParameters = BoundVar.copy(f.firstBlock.parameters);
         firstBlock.setParameters(BoundVar.concat(getParameters(), newParameters));
-        firstBlock.setExit(new Jump(f.firstBlock.createOccurrence(), ValRef.createOccurrences(newParameters)));
+        firstBlock.setExit(new Jump(-1, f.firstBlock.createOccurrence(), ValRef.createOccurrences(newParameters)));
         context.markModified("SSAFunction.simplify-simple-lambda");
     }
 
@@ -409,7 +409,7 @@ public final class SSAFunction extends SSAClosure {
             parameter.parent = firstBlock;
     }
     
-    public void apply(ValRef[] parameters) {
+    public void apply(int lineNumber, ValRef[] parameters) {
         if(parameters.length == 0)
             return;
         if(firstBlock.hasNoOccurences()) {
@@ -421,7 +421,7 @@ public final class SSAFunction extends SSAClosure {
         else {
             BoundVar[] newVars = new BoundVar[getArity()-parameters.length];
             SSABlock block = new SSABlock(newVars);
-            block.setExit(new Jump(firstBlock.createOccurrence(), 
+            block.setExit(new Jump(lineNumber, firstBlock.createOccurrence(), 
                     ValRef.concat(ValRef.copy(parameters), ValRef.createOccurrences(newVars))));
             addBlockInFront(block);
         }
index c9c8b35fb19c16a85714c027772d102c50e92c88..d25038117131d3376a094b3815134d9f268708b0 100644 (file)
@@ -107,7 +107,7 @@ public class SSAModule {
             System.out.println("Create class " + moduleClassName);
         final ClassBuilder classFile = new ClassBuilder(moduleBuilder, Opcodes.ACC_PUBLIC, moduleClassName,
                 "java/lang/Object");        
-        classFile.setSourceFile("_SCL_Module");
+        classFile.setSourceFile(moduleBuilder.getNamingPolicy().getModuleName());
         functions.forEachValue(new TObjectProcedure<SCLConstant>() {
             @Override
             public boolean execute(SCLConstant function) {
index a5d0bdc9f0dd32173d4ba33b3feac875ee101928..f83dcd3df7c18254c2f92b209d55ec7e557d5ef0 100644 (file)
@@ -23,7 +23,7 @@ public abstract class SSAStatement implements Printable {
     SSABlock parent;
     SSAStatement prev;
     SSAStatement next;
-    public long location;
+    public int lineNumber = -2;
     
     public void detach() {
         if(prev == null)
index 4eca7d1aeb35fa851124281175643a0f489025e7..ee69106cdb5f8dccace0220fcee6ebbf9adf0883 100644 (file)
@@ -31,7 +31,8 @@ public class If extends SSAExit implements ValRefBinder {
     private ContRef thenTarget;
     private ContRef elseTarget;
     
-    public If(ValRef condition, ContRef thenTarget, ContRef elseTarget) {
+    public If(int lineNumber, ValRef condition, ContRef thenTarget, ContRef elseTarget) {
+        super(lineNumber);
         setCondition(condition);
         setThenTarget(thenTarget);
         setElseTarget(elseTarget);
@@ -54,6 +55,7 @@ public class If extends SSAExit implements ValRefBinder {
 
     @Override
     public void generateCode(MethodBuilder mb) {
+        mb.lineNumber(lineNumber);
         Val binding = condition.getBinding();
         simplifyTestCode: if(binding instanceof BoundVar) {
             BoundVar boundVar = (BoundVar)binding;
@@ -147,9 +149,11 @@ public class If extends SSAExit implements ValRefBinder {
 
     @Override
     public SSAExit copy(CopyContext context) {
-        return new If(context.copy(condition),
+        If copy = new If(lineNumber,
+                context.copy(condition),
                 context.copy(thenTarget),
                 context.copy(elseTarget));
+        return copy;
     }
     
     @Override
@@ -163,11 +167,11 @@ public class If extends SSAExit implements ValRefBinder {
         if(cond instanceof BooleanConstant) {
             SSAExit newExit;
             if(((BooleanConstant) cond).getValue()) {
-                newExit = new Jump(thenTarget);
+                newExit = new Jump(lineNumber, thenTarget);
                 elseTarget.remove();
             }
             else {
-                newExit = new Jump(elseTarget);
+                newExit = new Jump(lineNumber, elseTarget);
                 thenTarget.remove();
             }
             condition.remove();
@@ -177,7 +181,7 @@ public class If extends SSAExit implements ValRefBinder {
         else if(thenTarget.getBinding() == elseTarget.getBinding()) {
             elseTarget.remove();
             condition.remove();
-            getParent().setExit(new Jump(thenTarget));
+            getParent().setExit(new Jump(lineNumber, thenTarget));
             context.markModified("equal-branches-if");
         }
     }
index eb1a3dea972dc61f05914b4c18e13015b37adf63..434e8644addb7e6e728326d43d2c83ba83dfa0da 100644 (file)
@@ -23,7 +23,8 @@ public class Jump extends SSAExit implements ValRefBinder {
     private ContRef target;
     private ValRef[] parameters;
     
-    public Jump(ContRef target, ValRef ... parameters) {
+    public Jump(int lineNumber, ContRef target, ValRef ... parameters) {
+        super(lineNumber);
         setTarget(target);
         setParameters(parameters);
     }
@@ -48,7 +49,8 @@ public class Jump extends SSAExit implements ValRefBinder {
     }
 
     @Override
-    public void generateCode(MethodBuilder mb) {        
+    public void generateCode(MethodBuilder mb) {
+        mb.lineNumber(lineNumber);
         mb.jump(target, ValRef.getBindings(parameters));
     }
 
@@ -91,7 +93,7 @@ public class Jump extends SSAExit implements ValRefBinder {
 
     @Override
     public SSAExit copy(CopyContext context) {
-        return new Jump(context.copy(target), context.copy(parameters));
+        return new Jump(lineNumber, context.copy(target), context.copy(parameters));
     }
     
     @Override
index b3584ae7e53692c5196bcf0f9f575723296f5117..55f38f809b540acbea4e3cf7baa47877e5965e1d 100644 (file)
@@ -34,7 +34,8 @@ public class Switch extends SSAExit implements ValRefBinder {
     ValRef scrutinee;
     BranchRef[] branches;
     
-    public Switch(ValRef scrutinee, BranchRef[] branches) {
+    public Switch(int lineNumber, ValRef scrutinee, BranchRef[] branches) {
+        super(lineNumber);
         this.scrutinee = scrutinee;
         this.branches = branches;
         scrutinee.setParent(this);
@@ -90,6 +91,7 @@ public class Switch extends SSAExit implements ValRefBinder {
 
     @Override
     public void generateCode(MethodBuilder mb) {
+        mb.lineNumber(lineNumber);
         if(isIntegerSwitch()) {
             generateIntegerSwitch(mb);
             return;
@@ -168,7 +170,7 @@ public class Switch extends SSAExit implements ValRefBinder {
     
     @Override
     public SSAExit copy(CopyContext context) {
-        return new Switch(context.copy(scrutinee), 
+        return new Switch(lineNumber, context.copy(scrutinee), 
                 BranchRef.copy(context, branches));
     }
 
@@ -221,10 +223,11 @@ public class Switch extends SSAExit implements ValRefBinder {
             SSAExit newExit;
             if(thenTarget == elseTarget) {
                 scrutinee.remove();
-                newExit = new Jump(thenTarget);
+                newExit = new Jump(lineNumber, thenTarget);
             }
             else {
-                newExit = new If(scrutinee, 
+                newExit = new If(lineNumber,
+                        scrutinee, 
                         thenTarget, 
                         elseTarget);
             }
@@ -234,7 +237,7 @@ public class Switch extends SSAExit implements ValRefBinder {
         }
         else if(branches.length == 1 && isConstructorParameterless(branches[0])) {
             scrutinee.remove();
-            getParent().setExit(new Jump(branches[0].cont));
+            getParent().setExit(new Jump(lineNumber, branches[0].cont));
         }
     }
     
index 593b81c63f2914c40355e47b7932336f3e0ced29..0193c99c2368fd8a690607438646f76e4bdad1ce 100644 (file)
@@ -30,7 +30,8 @@ public class Throw extends SSAExit {
     TypeDesc exceptionClass;
     String description;
     
-    public Throw(TypeDesc exceptionClass, String description) {
+    public Throw(int lineNumber, TypeDesc exceptionClass, String description) {
+        super(lineNumber);
         this.exceptionClass = exceptionClass;
         this.description = description;
     }
@@ -43,8 +44,7 @@ public class Throw extends SSAExit {
 
     @Override
     public void generateCode(MethodBuilder mb) {
-        //mb.push(exception.getBinding());
-        //cb.mapLineNumber(location);
+        mb.lineNumber(lineNumber);
         mb.newObject(exceptionClass);
         mb.dup();
         if(description == null)
@@ -67,7 +67,7 @@ public class Throw extends SSAExit {
 
     @Override
     public SSAExit copy(CopyContext context) {
-        return new Throw(exceptionClass, description);
+        return new Throw(lineNumber, exceptionClass, description);
     }
     
     @Override
index 78353b42419c54832c4b9d553754a30b79279a10..97fba708db5a4de52c830ef7d8e7362c377ca642 100644 (file)
@@ -21,7 +21,8 @@ public class Throw2 extends SSAExit {
 
     ValRef exception;
     
-    public Throw2(ValRef exception) {
+    public Throw2(int lineNumber, ValRef exception) {
+        super(lineNumber);
         this.exception = exception;
     }
 
@@ -34,6 +35,7 @@ public class Throw2 extends SSAExit {
 
     @Override
     public void generateCode(MethodBuilder mb) {
+        mb.lineNumber(lineNumber);
         mb.pushBoxed(exception.getBinding());
         mb.throwObject();
     }
@@ -49,7 +51,7 @@ public class Throw2 extends SSAExit {
 
     @Override
     public SSAExit copy(CopyContext context) {
-        return new Throw2(exception.copy());
+        return new Throw2(lineNumber, exception.copy());
     }
     
     @Override
index 2733868cf06d312ac82f0a687840b4ca4a2420ff..b4c2955385954515a8a516d7d4dd855c9a2d20db 100644 (file)
@@ -55,7 +55,7 @@ public class LetApply extends LetStatement implements ValRefBinder {
     }
 
     public void push(MethodBuilder mb) {
-        //mb.getCodeBuilder().mapLineNumber(lineNumber);
+        int oldLineNumber = mb.lineNumber(lineNumber);
         Val f = getFunction().getBinding();
         Val[] ps = ValRef.getBindings(getParameters());
         if(f instanceof Constant) {
@@ -70,11 +70,13 @@ public class LetApply extends LetStatement implements ValRefBinder {
             mb.genericApply(ps.length);
             mb.unbox(target.getType());
         }
+        mb.lineNumber(oldLineNumber);
     }
     
     @Override
     public void generateCode(MethodBuilder mb) {
         if(!target.generateOnFly) {
+            mb.lineNumber(lineNumber);
             push(mb);
             mb.store(target);
         }
@@ -101,6 +103,7 @@ public class LetApply extends LetStatement implements ValRefBinder {
     public void bodyToString(PrintingContext context) {
         if(context.getErrorMarker() == this)
             context.append("!> ");
+        context.append("L" + lineNumber + ": ");
         if(hasEffect()) {
             context.append("<");
             context.append(effect);
@@ -417,8 +420,7 @@ public class LetApply extends LetStatement implements ValRefBinder {
         // Merge blocks        
         thisFunction.mergeBlocks(function);
         
-        headBlock.setExit(new Jump(function.getFirstBlock().createOccurrence(), 
-                parameters));
+        headBlock.setExit(new Jump(lineNumber, function.getFirstBlock().createOccurrence(), parameters));
         function.getReturnCont().replaceWith(tailBlock);
 
         this.function.remove();
index bd1a911a15f4ec4fe2342284baec23414da7a1a2..51a93c53c8c09589198e3c62b79ac1f1c2eeef74 100644 (file)
@@ -12,6 +12,7 @@ public class MethodBuilderBase {
     private MethodVisitor methodVisitor;
     private LocalVariable[] parameters;
     private int localVariableCount = 0;
+    private int currentLineNumber = -1;
     
     public MethodBuilderBase(ClassBuilder classBuilder, boolean isStatic, MethodVisitor methodVisitor, TypeDesc[] parameterTypes) {
         this.classBuilder = classBuilder;
@@ -87,6 +88,20 @@ public class MethodBuilderBase {
             methodVisitor.visitLdcInsn(Type.getType(value.getDescriptor()));
     }
 
+    
+    public int lineNumber(int lineNumber) {
+        if(lineNumber != currentLineNumber) {
+            int oldLineNumber = currentLineNumber;
+            Label label = createLabel();
+            setLocation(label);
+            methodVisitor.visitLineNumber(lineNumber, label);
+            currentLineNumber = lineNumber;
+            return oldLineNumber;
+        }
+        else
+            return currentLineNumber;
+    }
+
     public void dup() {
         methodVisitor.visitInsn(Opcodes.DUP);
     }
index 1125a4bde9f41c52f372adcd22c9c627dc6f9010..bb774bd24e798b10cbd3ce1d58cf4bdc8c85fb6a 100644 (file)
@@ -2,6 +2,7 @@ package org.simantics.scl.compiler.internal.codegen.writer;
 
 import org.cojen.classfile.TypeDesc;
 import org.simantics.scl.compiler.common.exceptions.InternalCompilerError;
+import org.simantics.scl.compiler.errors.Locations;
 import org.simantics.scl.compiler.internal.codegen.continuations.Branch;
 import org.simantics.scl.compiler.internal.codegen.continuations.BranchRef;
 import org.simantics.scl.compiler.internal.codegen.continuations.ICont;
@@ -33,11 +34,22 @@ public class CodeWriter {
         this.moduleWriter = moduleWriter;
         this.block = block;
     }
+    
+    private int lineNumber(long location) {
+        if(location == Locations.NO_LOCATION)
+            return -1;
+        else {
+            int position = Locations.beginOf(location);
+            int line = moduleWriter.lineLocator.lineNumberFromPosition(position);
+            //System.out.println("location=" + location + ", position=" + position + ", line=" + line);
+            return line + 1;
+        }
+    }
 
-    public IVal apply(long lineNumber, IVal function, IVal ... parameters) {
+    public IVal apply(long location, IVal function, IVal ... parameters) {
         try {
             MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);
-            return applyWithEffect(lineNumber,
+            return applyWithEffect(location,
                     mfun.effect,
                     mfun.returnType,
                     function, parameters);
@@ -46,7 +58,7 @@ public class CodeWriter {
         }
     }
     
-    public IVal applyWithEffectChecked(long lineNumber, Type effect, Type returnType, IVal function, IVal ... parameters) {
+    public IVal applyWithEffectChecked(long location, Type effect, Type returnType, IVal function, IVal ... parameters) {
         try {
             MultiFunction mfun = Types.matchFunction(function.getType(), parameters.length);
             if(!Types.equals(effect, mfun.effect))
@@ -56,7 +68,7 @@ public class CodeWriter {
         } catch (MatchException e) {
             throw new InternalCompilerError(e);
         }            
-        return applyWithEffect(lineNumber, effect, returnType, function, parameters);
+        return applyWithEffect(location, effect, returnType, function, parameters);
     }
     
     public IVal applyWithEffect(long location, Type effect, Type returnType, IVal function, IVal ... parameters) {
@@ -65,7 +77,7 @@ public class CodeWriter {
                 effect,
                 function.createOccurrence(), 
                 ValRef.createOccurrences(parameters));
-        apply.location = location;
+        apply.lineNumber = lineNumber(location);
         block.addStatement(apply);
         return var;
     }
@@ -115,49 +127,56 @@ public class CodeWriter {
         return block;
     }
     
-    public void jump(ICont cont, IVal ... parameters) {
-        block.setExit(new Jump(cont.createOccurrence(), 
+    public void jump(long location, ICont cont, IVal ... parameters) {
+        block.setExit(new Jump(
+                lineNumber(location),
+                cont.createOccurrence(), 
                 ValRef.createOccurrences(parameters)));
         block = null;
     }
     
-    public void if_(IVal condition, ICont thenTarget, ICont elseTarget) {
-        block.setExit(new If(condition.createOccurrence(), 
+    public void if_(long location, IVal condition, ICont thenTarget, ICont elseTarget) {
+        block.setExit(new If(
+                lineNumber(location),
+                condition.createOccurrence(), 
                 thenTarget.createOccurrence(), 
                 elseTarget.createOccurrence()));
         block = null;
     }
     
-    public void branchAwayIf(IVal condition, ICont target) {
+    public void branchAwayIf(long location, IVal condition, ICont target) {
         SSABlock newBlock = new SSABlock(Type.EMPTY_ARRAY);
         block.getParent().addBlock(newBlock);
-        block.setExit(new If(condition.createOccurrence(), 
+        block.setExit(new If(
+                lineNumber(location),
+                condition.createOccurrence(), 
                 target.createOccurrence(), 
                 newBlock.createOccurrence()));
         this.block = newBlock;
     }
     
-    public void branchAwayUnless(IVal condition, ICont target) {
+    public void branchAwayUnless(long location, IVal condition, ICont target) {
         SSABlock newBlock = new SSABlock(Type.EMPTY_ARRAY);
         block.getParent().addBlock(newBlock);
-        block.setExit(new If(condition.createOccurrence(), 
+        block.setExit(new If(
+                lineNumber(location),
+                condition.createOccurrence(), 
                 newBlock.createOccurrence(),
                 target.createOccurrence()));
         this.block = newBlock;
     }
 
-    public void return_(IVal val) {
-        jump(block.getParent().getReturnCont(), val);
+    public void return_(long location, IVal val) {
+        jump(lineNumber(location), block.getParent().getReturnCont(), val);
     }
 
-    public void switch_(IVal val, Branch[] branches) {
-        block.setExit(new Switch(val.createOccurrence(), BranchRef.toBranchRefs(branches)));
+    public void switch_(long location, IVal val, Branch[] branches) {
+        block.setExit(new Switch(lineNumber(location), val.createOccurrence(), BranchRef.toBranchRefs(branches)));
         block = null;
     }
 
     public void throw_(long location, TypeDesc exceptionClass, String description) {
-        Throw exit = new Throw(exceptionClass, description);
-        exit.location = location;
+        Throw exit = new Throw(lineNumber(location), exceptionClass, description);
         block.setExit(exit);
         block = null;
     }
index da986195b51000d091ed1f622b3b4c021b97ab68..e663c814e2f60b006fd06493ea11782795d98530 100644 (file)
@@ -10,6 +10,7 @@ import org.simantics.scl.compiler.internal.codegen.ssa.SSABlock;
 import org.simantics.scl.compiler.internal.codegen.ssa.SSAFunction;
 import org.simantics.scl.compiler.internal.codegen.ssa.SSAModule;
 import org.simantics.scl.compiler.internal.codegen.ssa.StaticField;
+import org.simantics.scl.compiler.internal.parsing.utils.LineLocator;
 import org.simantics.scl.compiler.types.TVar;
 import org.simantics.scl.compiler.types.Type;
 import org.simantics.scl.runtime.tuple.Tuple2;
@@ -19,15 +20,17 @@ import gnu.trove.map.hash.THashMap;
 public class ModuleWriter {
     
     SSAModule module;
+    LineLocator lineLocator;
     
     String moduleClassName;
     THashMap<Tuple2, JavaStaticField> externalConstantMap = 
                new THashMap<Tuple2, JavaStaticField>();
     int externalConstantId = 0;
     
-    public ModuleWriter(String moduleClassName) {
+    public ModuleWriter(String moduleClassName, LineLocator lineLocator) {
         this.module = new SSAModule();
         this.moduleClassName = moduleClassName;
+        this.lineLocator = lineLocator;
     }
 
     public CodeWriter createFunction(SCLConstant constant, TVar[] typeParameters,
index 62b2ec1aaf4bc9894d14d8dabb957c80b234853f..64bf7053b14d0526310fc0fcb4eae4fe149f2b7a 100644 (file)
@@ -55,7 +55,7 @@ public class PatternMatchingCompiler {
         return newVals;
     }
 
-    private static void splitByConstructors(CodeWriter w, final CompilationContext context, IVal[] scrutinee, final ICont success, ICont failure, List<Row> rows, int columnId) {
+    private static void splitByConstructors(long location, CodeWriter w, final CompilationContext context, IVal[] scrutinee, final ICont success, ICont failure, List<Row> rows, int columnId) {
         THashMap<Object, ExpressionMatrix> matrixMap = new THashMap<Object, ExpressionMatrix>();
         ArrayList<Branch> branches = new ArrayList<Branch>();
         ArrayList<ExpressionMatrix> matrices = new ArrayList<ExpressionMatrix>();
@@ -168,7 +168,7 @@ public class PatternMatchingCompiler {
             CodeWriter newW = w.createBlock();
             ICont cont = newW.getContinuation();
             branches.add(new Branch(null, cont));
-            split(newW, context, scrutinee, success, failure, rows.subList(i, rows.size()));
+            split(location, newW, context, scrutinee, success, failure, rows.subList(i, rows.size()));
             failure = cont;
         }
         else {
@@ -186,11 +186,11 @@ public class PatternMatchingCompiler {
         }
 
         for(ExpressionMatrix mx : matrices)
-            split(mx.w, context, mx.scrutinee, success, failure, mx.rows);
-        w.switch_(scrutinee[columnId], branches.toArray(new Branch[branches.size()]));
+            split(location, mx.w, context, mx.scrutinee, success, failure, mx.rows);
+        w.switch_(location, scrutinee[columnId], branches.toArray(new Branch[branches.size()]));
     }
 
-    private static void splitByViewPattern(CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont success,
+    private static void splitByViewPattern(long location, CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont success,
             ICont failure, List<Row> rows, int viewPatternColumn) {
         Row firstRow = rows.get(0);
         EViewPattern firstViewPattern = (EViewPattern)firstRow.patterns[viewPatternColumn];
@@ -225,16 +225,16 @@ public class PatternMatchingCompiler {
                         firstViewPattern.expression.toVal(context, w),
                         scrutinee[viewPatternColumn]);
         if(i == rows.size()) {
-            split(w, context, newScrutinee, success, failure, rows);
+            split(location, w, context, newScrutinee, success, failure, rows);
         }
         else {
             CodeWriter cont = w.createBlock();
-            split(w, context, newScrutinee, success, cont.getContinuation(), rows.subList(0, i));
-            split(cont, context, scrutinee, success, failure, rows.subList(i, rows.size()));
+            split(location, w, context, newScrutinee, success, cont.getContinuation(), rows.subList(0, i));
+            split(location, cont, context, scrutinee, success, failure, rows.subList(i, rows.size()));
         }
     }
 
-    public static void split(CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont success, ICont failure, List<Row> rows) {
+    public static void split(long location, CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont success, ICont failure, List<Row> rows) {
         Row firstRow = rows.get(0);
         Expression[] patterns = firstRow.patterns;
         if(scrutinee.length != patterns.length)
@@ -249,13 +249,13 @@ public class PatternMatchingCompiler {
                     viewPatternColumn = i;
             }
             else if(!(pattern instanceof EVariable)) {
-                splitByConstructors(w, context, scrutinee, success, failure, rows, i);
+                splitByConstructors(location, w, context, scrutinee, success, failure, rows, i);
                 return;
             }
         }
         
         if(viewPatternColumn >= 0) {
-            splitByViewPattern(w, context, scrutinee, success, failure, rows, viewPatternColumn);
+            splitByViewPattern(location, w, context, scrutinee, success, failure, rows, viewPatternColumn);
             return;
         }
 
@@ -271,10 +271,10 @@ public class PatternMatchingCompiler {
                 CodeWriter newW = w.createBlock();            
                 ICont cont = newW.getContinuation();
                 group.compile(context, w, success, cont);
-                split(newW, context, scrutinee, success, failure, rows.subList(1, rows.size()));
+                split(location, newW, context, scrutinee, success, failure, rows.subList(1, rows.size()));
             }
         }
         else
-            w.jump(success, firstRow.value.toVal(context, w));
+            w.jump(location, success, firstRow.value.toVal(context, w));
     }
 }
index 24a3bfb2edcc2e8208aefa4435974fec8b31af47..41882f57a5d86448a98ec049cd2783d6cf4ed58b 100644 (file)
@@ -54,7 +54,7 @@ public class PatternMatchingCompiler2 {
         return newVals;
     }
 
-    private static void splitByConstructors(CodeWriter w, final CompilationContext context, IVal[] scrutinee, ICont failure, List<Row2> rows, int columnId) {
+    private static void splitByConstructors(long location, CodeWriter w, final CompilationContext context, IVal[] scrutinee, ICont failure, List<Row2> rows, int columnId) {
         THashMap<Object, ExpressionMatrix> matrixMap = new THashMap<Object, ExpressionMatrix>();
         ArrayList<Branch> branches = new ArrayList<Branch>();
         ArrayList<ExpressionMatrix> matrices = new ArrayList<ExpressionMatrix>();
@@ -167,7 +167,7 @@ public class PatternMatchingCompiler2 {
             CodeWriter newW = w.createBlock();
             ICont cont = newW.getContinuation();
             branches.add(new Branch(null, cont));
-            split(newW, context, scrutinee, failure, rows.subList(i, rows.size()));
+            split(location, newW, context, scrutinee, failure, rows.subList(i, rows.size()));
             failure = cont;
         }
         else {
@@ -185,11 +185,11 @@ public class PatternMatchingCompiler2 {
         }
 
         for(ExpressionMatrix mx : matrices)
-            split(mx.w, context, mx.scrutinee, failure, mx.rows);
-        w.switch_(scrutinee[columnId], branches.toArray(new Branch[branches.size()]));
+            split(location, mx.w, context, mx.scrutinee, failure, mx.rows);
+        w.switch_(location, scrutinee[columnId], branches.toArray(new Branch[branches.size()]));
     }
 
-    private static void splitByViewPattern(CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont failure, List<Row2> rows, int viewPatternColumn) {
+    private static void splitByViewPattern(long location, CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont failure, List<Row2> rows, int viewPatternColumn) {
         Row2 firstRow = rows.get(0);
         EViewPattern firstViewPattern = (EViewPattern)firstRow.patterns[viewPatternColumn];
         firstRow.patterns[viewPatternColumn] = firstViewPattern.pattern;
@@ -223,16 +223,16 @@ public class PatternMatchingCompiler2 {
                         firstViewPattern.expression.toVal(context, w),
                         scrutinee[viewPatternColumn]);
         if(i == rows.size()) {
-            split(w, context, newScrutinee, failure, rows);
+            split(location, w, context, newScrutinee, failure, rows);
         }
         else {
             CodeWriter cont = w.createBlock();
-            split(w, context, newScrutinee, cont.getContinuation(), rows.subList(0, i));
-            split(cont, context, scrutinee, failure, rows.subList(i, rows.size()));
+            split(location, w, context, newScrutinee, cont.getContinuation(), rows.subList(0, i));
+            split(location, cont, context, scrutinee, failure, rows.subList(i, rows.size()));
         }
     }
 
-    public static void split(CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont failure, List<Row2> rows) {
+    public static void split(long location, CodeWriter w, CompilationContext context, IVal[] scrutinee, ICont failure, List<Row2> rows) {
         Row2 firstRow = rows.get(0);
         Expression[] patterns = firstRow.patterns;
         if(scrutinee.length != patterns.length)
@@ -247,19 +247,19 @@ public class PatternMatchingCompiler2 {
                     viewPatternColumn = i;
             }
             else if(!(pattern instanceof EVariable)) {
-                splitByConstructors(w, context, scrutinee, failure, rows, i);
+                splitByConstructors(location, w, context, scrutinee, failure, rows, i);
                 return;
             }
         }
         
         if(viewPatternColumn >= 0) {
-            splitByViewPattern(w, context, scrutinee, failure, rows, viewPatternColumn);
+            splitByViewPattern(location, w, context, scrutinee, failure, rows, viewPatternColumn);
             return;
         }
 
         // The first row has only variable patterns: no matching needed
         for(int i=0;i<patterns.length;++i)
             ((EVariable)patterns[i]).getVariable().setVal(scrutinee[i]);
-        w.jump(firstRow.continuation);
+        w.jump(location, firstRow.continuation);
     }
 }
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/utils/LineLocator.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/utils/LineLocator.java
new file mode 100644 (file)
index 0000000..f447451
--- /dev/null
@@ -0,0 +1,15 @@
+package org.simantics.scl.compiler.internal.parsing.utils;
+
+public abstract class LineLocator {
+    final protected int[] rowStarts;
+    
+    public LineLocator(int[] rowStarts) {
+        this.rowStarts = rowStarts;
+    }
+    
+    public abstract int lineNumberFromPosition(int position);
+    
+    public int columnNumber(int line, int position) {
+        return position - rowStarts[line];
+    }
+}
diff --git a/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/utils/LineLocators.java b/bundles/org.simantics.scl.compiler/src/org/simantics/scl/compiler/internal/parsing/utils/LineLocators.java
new file mode 100644 (file)
index 0000000..63b2baf
--- /dev/null
@@ -0,0 +1,185 @@
+package org.simantics.scl.compiler.internal.parsing.utils;
+
+import gnu.trove.list.array.TIntArrayList;
+
+public class LineLocators {
+
+    private static class ByteArrayLineLocator extends LineLocator {
+        private final byte[] lineNumbers;
+        private final int maxLine;
+        
+        public ByteArrayLineLocator(int[] rowStarts) {
+            super(rowStarts);
+            int lastRow = rowStarts.length-1;
+            this.lineNumbers = new byte[rowStarts[lastRow]];
+            this.maxLine = rowStarts.length-1;
+            
+            int position = 0;
+            int line = 0;
+            while(line < maxLine) {
+                int endPosition = rowStarts[line+1];
+                while(position < endPosition)
+                    lineNumbers[position++] = (byte)line;
+                ++line;
+            }
+        }
+        
+        @Override
+        public int lineNumberFromPosition(int position) {
+            if(position <= 0)
+                return 0;
+            if(position >= lineNumbers.length)
+                return maxLine;
+            return (int)lineNumbers[position];
+        }
+    }
+    
+    private static class CharArrayLineLocator extends LineLocator {
+        private final char[] lineNumbers;
+        private final int maxLine;
+        
+        public CharArrayLineLocator(int[] rowStarts) {
+            super(rowStarts);
+            int lastRow = rowStarts.length-1;
+            this.lineNumbers = new char[rowStarts[lastRow]];
+            this.maxLine = rowStarts.length-1;
+            
+            int position = 0;
+            int line = 0;
+            while(line < maxLine) {
+                int endPosition = rowStarts[line+1];
+                while(position < endPosition)
+                    lineNumbers[position++] = (char)line;
+                ++line;
+            }
+        }
+        
+        @Override
+        public int lineNumberFromPosition(int position) {
+            if(position <= 0)
+                return 0;
+            if(position >= lineNumbers.length)
+                return maxLine;
+            return (int)lineNumbers[position];
+        }
+    }
+    
+    private static class IntArrayLineLocator extends LineLocator {
+        private final int[] lineNumbers;
+        private final int maxLine;
+        
+        public IntArrayLineLocator(int[] rowStarts) {
+            super(rowStarts);
+            int lastRow = rowStarts.length-1;
+            this.lineNumbers = new int[rowStarts[lastRow]];
+            this.maxLine = rowStarts.length-1;
+            
+            int position = 0;
+            int line = 0;
+            while(line < maxLine) {
+                int endPosition = rowStarts[line+1];
+                while(position < endPosition)
+                    lineNumbers[position++] = line;
+                ++line;
+            }
+        }
+        
+        @Override
+        public int lineNumberFromPosition(int position) {
+            if(position <= 0)
+                return 0;
+            if(position >= lineNumbers.length)
+                return maxLine;
+            return lineNumbers[position];
+        }
+    }
+    
+    private static class BinarySearchLineLocator extends LineLocator {
+        public BinarySearchLineLocator(int[] rowStarts) {
+            super(rowStarts);
+        }
+
+        @Override
+        public int lineNumberFromPosition(int position) {
+            if(position <= 0)
+                return 0;
+            if(position >= rowStarts[rowStarts.length-1])
+                return rowStarts.length-1;
+            int low = 0;
+            int high = rowStarts.length-1;
+            // invariant, low <= lineNumber < high
+            while(low < high-1) {
+                int middle = (low+high) / 2;
+                if(position < rowStarts[middle])
+                    high = middle;
+                else
+                    low = middle;
+            }
+            return low;
+        }
+    }
+    
+    private static class InterpolationSearchLineLocator extends LineLocator {
+        public InterpolationSearchLineLocator(int[] rowStarts) {
+            super(rowStarts);
+        }
+
+        @Override
+        public int lineNumberFromPosition(int position) {
+            if(position <= 0)
+                return 0;
+            if(position >= rowStarts[rowStarts.length-1])
+                return rowStarts.length-1;
+            int low = 0;
+            int lowPosition = 0;
+            int high = rowStarts.length-1;
+            int highPosition = rowStarts[high];
+            // invariant, low <= lineNumber < high
+            while(low < high-1) {
+                int delta = (int)((long)(high - low) * (position - lowPosition) / (highPosition - lowPosition));
+                int middle = low + delta;
+                if(middle == low)
+                    ++middle;
+                if(position < rowStarts[middle]) {
+                    high = middle;
+                    highPosition = rowStarts[high];
+                }
+                else {
+                    low = middle;
+                    lowPosition = rowStarts[low];
+                }
+            }
+            return low;
+        }
+    }
+
+    public static final LineLocator DUMMY_LOCATOR = new LineLocator(new int[] {0}) {
+        @Override
+        public int lineNumberFromPosition(int position) {
+            return 0;
+        }
+    };
+    
+    private static int[] findRowStarts(String source) {
+        TIntArrayList rowStarts = new TIntArrayList();
+        rowStarts.add(0);
+
+        int length = source.length();
+        for(int i=0;i<length;++i) {
+            char c = source.charAt(i);
+            if(c == '\n')
+                rowStarts.add(i+1);
+        }
+        return rowStarts.toArray();
+    }
+
+    public static LineLocator createLineLocator(String source) {
+        int[] rowStarts = findRowStarts(source);
+        if(rowStarts.length <= Byte.MAX_VALUE)
+            return new ByteArrayLineLocator(rowStarts);
+        else if(rowStarts.length <= Character.MAX_VALUE)
+            return new CharArrayLineLocator(rowStarts);
+        else
+            return new InterpolationSearchLineLocator(rowStarts);
+    }
+}
index 472c0dc1b53e8097290fb27f8731f5ce35c4d05a..1a4bc9332fd15e1525ba873878d0c92ef705d74c 100644 (file)
@@ -1,8 +1,6 @@
 package org.simantics.scl.compiler.source;
 
 import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
 
 import org.simantics.scl.compiler.internal.codegen.types.JavaReferenceValidator;
 import org.simantics.scl.compiler.internal.codegen.types.RuntimeJavaReferenceValidator;
@@ -23,9 +21,8 @@ public class StringModuleSource extends TextualModuleSource {
     }
     
     @Override
-    protected Reader getSourceReader(UpdateListener listener)
-            throws IOException {
-        return new StringReader(moduleText);
+    public String getSourceText(UpdateListener listener) throws IOException {
+        return moduleText;
     }
     
     @Override
index e0d1c91e4da51e3b6b0b8d583b848857ae9a11b6..7d0e5335281684aac58ea296d1f51bf71875576c 100644 (file)
@@ -2,6 +2,7 @@ package org.simantics.scl.compiler.source;
 
 import java.io.IOException;
 import java.io.Reader;
+import java.io.StringReader;
 import java.util.Arrays;
 
 import org.simantics.scl.compiler.compilation.SCLCompiler;
@@ -46,14 +47,17 @@ public abstract class TextualModuleSource implements ModuleSource {
         return getClass().getClassLoader();
     }
 
-    protected abstract Reader getSourceReader(UpdateListener listener) throws IOException;
+    protected Reader getSourceReader(UpdateListener listener) throws IOException {
+        return new StringReader(getSourceText(listener));
+    }
+    
     protected JavaReferenceValidator<?, ?, ?, ?> getJavaReferenceValidator() {
         return new RuntimeJavaReferenceValidator(getClassLoader());
     }
     
     public String getSourceText(UpdateListener listener) throws IOException {
         Reader reader = getSourceReader(listener);
-        char[] buffer = new char[65536];
+        char[] buffer = new char[4096];
         int pos = 0;
         try {
             while(true) {
@@ -83,7 +87,8 @@ public abstract class TextualModuleSource implements ModuleSource {
     public Failable<Module> compileModule(final ModuleRepository environment, final UpdateListener listener, ModuleCompilationOptions options) {
         SCLCompiler compiler = new SCLCompiler(options, getJavaReferenceValidatorFactory());
         try {
-            compiler.addSource(getSourceReader(listener));
+            String source = getSourceText(listener);
+            compiler.addSource(source);
             compiler.compile(
                     new EnvironmentFactoryImpl(
                             environment, 
index 36994d136533435522642855fdf5a8817203fd57..b51b188cda117823c4d8b0308f13eb607615aa91 100644 (file)
@@ -47,6 +47,7 @@ import org.simantics.scl.compiler.internal.parsing.exceptions.SCLSyntaxErrorExce
 import org.simantics.scl.compiler.internal.parsing.parser.SCLBlockParser;
 import org.simantics.scl.compiler.internal.parsing.parser.SCLParserImpl;
 import org.simantics.scl.compiler.internal.parsing.parser.SCLParserOptions;
+import org.simantics.scl.compiler.internal.parsing.utils.LineLocators;
 import org.simantics.scl.compiler.runtime.MutableClassLoader;
 import org.simantics.scl.compiler.runtime.RuntimeEnvironment;
 import org.simantics.scl.compiler.types.TVar;
@@ -202,6 +203,7 @@ public class ExpressionEvaluator {
         
         // Parse expression
         if(expressionText != null) {
+            compilationContext.lineLocator = LineLocators.createLineLocator(expressionText);
             try {
                 switch(parseMode) {
                 case BLOCK: {
@@ -230,6 +232,8 @@ public class ExpressionEvaluator {
                 throw new SCLExpressionCompilationException(errorLog.getErrors());
             }
         }
+        else
+            compilationContext.lineLocator = LineLocators.DUMMY_LOCATOR;
         
         // Store local variables
         ArrayList<Type> lvTypes = new ArrayList<Type>(); 
@@ -364,7 +368,7 @@ public class ExpressionEvaluator {
         }
         
         // Convert to SSA
-        ModuleWriter mw = new ModuleWriter(namingPolicy.getModuleClassName());
+        ModuleWriter mw = new ModuleWriter(namingPolicy.getModuleClassName(), compilationContext.lineLocator);
         DecomposedExpression decomposed = 
                 DecomposedExpression.decompose(errorLog, expression);
 
@@ -387,9 +391,10 @@ public class ExpressionEvaluator {
             IVal[] parameterVals = w.getParameters();
             for(int i=0;i<decomposed.parameters.length;++i)
                 decomposed.parameters[i].setVal(parameterVals[i]);
-            w.return_(decomposed.body.toVal(compilationContext, w));
+            w.return_(decomposed.body.location, decomposed.body.toVal(compilationContext, w));
         } catch(RuntimeException e) {
             errorLog.setExceptionPosition(expression.location);
+            errorLog.log(e);
             throw new SCLExpressionCompilationException(errorLog.getErrors());
         }
 
index d057daccb45d42c18036da9c1d465899ae6d2196..02ded78809c37abd5b7e7b61dc06be20d3fc3960 100644 (file)
@@ -1,8 +1,6 @@
 package org.simantics.tests.modelled.ui;
 
 import java.io.IOException;
-import java.io.Reader;
-import java.io.StringReader;
 
 import org.eclipse.ui.IPersistableElement;
 import org.simantics.Simantics;
@@ -81,8 +79,8 @@ public class STSTestEditorInput extends StandardSCLModuleEditorInput  {
         }
 
         @Override
-        protected Reader getSourceReader(UpdateListener listener) throws IOException {
-            return new StringReader(moduleText);
+        public String getSourceText(UpdateListener listener) throws IOException {
+            return moduleText;
         }
     }