Initial commit of main compiler sources (or should I say ... SAUCES!)

This commit is contained in:
2025-06-08 23:58:21 +10:00
parent 60c566025c
commit 06f2613083
214 changed files with 22210 additions and 0 deletions

View File

@@ -0,0 +1,68 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.bytecode.TypeSignature;
import slangc.model.ExpressionModel;
import slangc.model.ExpressionOwner;
import slangc.model.InnerTypeScope;
import slangc.model.MemberModel;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.parser.Branch;
import slangc.parser.Node;
public class AssertStatement extends StatementModel implements ExpressionOwner {
private ExpressionModel expression;
public AssertStatement(StatementOwner owner, Branch source) {
super(owner, source);
expression = ExpressionModel.construct(this, source.getSubnode(1));
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Assert:");
expression.dump(reporter, indent + incr, incr);
}
@Override
public int resolveExpressions() {
return expression.resolveExpressions();
}
public ExpressionModel getExpression() {
return expression;
}
//@Override
public TypeModel getExpectedResult(ExpressionModel e) {
// TODO: Should probably be boolean or some configurable type
return null;
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner().getTypeScope();
}
//@Override
public TypeModel resolveType(Node subnode) {
return getOwner().resolveType(subnode);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
//@Override
public void innerGenerate(BytecodeInstructionWriter w) {
TypeSignature t = getExpression().generate(w);
w.genDrop(t); // TODO: Check result and/or something like w.genThrow();
}
}

View File

@@ -0,0 +1,109 @@
package slangc.model.statements;
import slang.data.List;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.model.InnerTypeScope;
import slangc.model.MemberModel;
import slangc.model.Named;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.parser.Branch;
import slangc.parser.Node;
import slangc.parser.NodeType;
public class BlockStatement extends StatementModel implements StatementOwner {
private List<StatementModel> statements = new List<StatementModel>();
private InnerTypeScope.SourceScope typeScope;
public BlockStatement(StatementOwner owner, Branch source) {
super(owner, source);
typeScope = owner.getTypeScope().getInnerScopeForSource(source);
//System.err.println("Block scope for " + this + " is " + typeScope);
if (typeScope != null && typeScope.source != source) {
throw new Error("Mismatched scope!");
}
Branch inner = (Branch) source.getSubnode(1);
for (int i = 0; i < inner.countSubnodes(); i++) {
if (inner.getSubnode(i).getNodeType() != NodeType.SEMICOLON) {
statements.append(StatementModel.construct(this, inner.getSubnode(i)));
}
}
}
//@Override
public InnerTypeScope getTypeScope() {
return typeScope == null ? getOwner().getTypeScope() : typeScope;
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Block statement:");
for (int i = 0; i < statements.count(); i++) {
StatementModel s = statements.get(i);
s.dump(reporter, indent + incr, incr);
}
}
//@Override
public TypeModel resolveType(Node subnode) {
return getTypeScope().resolveTypeReference(subnode);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
@Override
public Named lookupSimpleName(String name) {
for (int i = 0; i < statements.count(); i++) {
StatementModel s = statements.get(i);
if (s instanceof VariableStatement) {
VariableStatement vs = (VariableStatement) s;
if (vs.hasVariable(name)) {
return vs.getVariable(name);
}
}
}
if (typeScope != null) {
if (typeScope.hasInnerType(name)) {
return typeScope.getInnerType(name);
}
}
return super.lookupSimpleName(name);
}
@Override
public int resolveExpressions() {
int nresolved = 0;
for (int i = 0; i < statements.count(); i++) {
StatementModel s = statements.get(i);
nresolved = s.resolveExpressions();
}
return nresolved;
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
for (int i = 0; i < statements.count(); i++) {
StatementModel s = statements.get(i);
s.generate(w);
}
}
public int countInnerStatements() {
return statements.count();
}
public StatementModel getInnerStatement(int i) {
return statements.get(i);
}
public MethodModel[] lookupSimpleMethod(String name) {
// TODO: Better interface support
return super.lookupSimpleMethod(name);
}
}

View File

@@ -0,0 +1,33 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.parser.Node;
public class BreakStatement extends StatementModel {
public BreakStatement(StatementOwner owner, Node source) {
super(owner, source);
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Break (no label)");
}
@Override
public int resolveExpressions() {
return 0;
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
if (w.getBreak() == null) {
w.genError("Nowhere to break to");
} else {
w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, w.getBreak());
}
}
}

View File

@@ -0,0 +1,77 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.model.ExpressionModel;
import slangc.model.ExpressionOwner;
import slangc.model.InnerTypeScope;
import slangc.model.MemberModel;
import slangc.model.Named;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.parser.Branch;
import slangc.parser.Node;
public class CaseLabelStatement extends StatementModel implements ExpressionOwner {
private ExpressionModel expression;
public CaseLabelStatement(StatementOwner owner, Branch source) {
super(owner, source);
expression = ExpressionModel.construct(this, source.getSubnode(1));
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Case (label):");
expression.dump(reporter, indent + incr, incr);
}
public ExpressionModel getExpression() {
return expression;
}
//@Override
public TypeModel getExpectedResult(ExpressionModel e) {
// TODO Can probably be determined
return null;
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner().getTypeScope();
}
//@Override
public TypeModel resolveType(Node subnode) {
return getOwner().resolveType(subnode);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
@Override
public Named lookupSimpleName(String name) {
// TODO: Work out whether enum-switch scope applies only to labels or everywhere inside the switch scope
return getOwner().lookupSimpleName(name);
}
@Override
public int resolveExpressions() {
// TODO: Check that a case label refers to a usable constant at some point
return expression.resolveExpressions();
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
}
public MethodModel[] lookupSimpleMethod(String name) {
// TODO: Better interface support
return super.lookupSimpleMethod(name);
}
}

View File

@@ -0,0 +1,33 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.parser.Node;
public class ContinueStatement extends StatementModel {
public ContinueStatement(StatementOwner owner, Node source) {
super(owner, source);
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Continue (no label)");
}
@Override
public int resolveExpressions() {
return 0;
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
if (w.getContinue() == null) {
w.genError("Nowhere to continue to");
} else {
w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, w.getContinue());
}
}
}

View File

@@ -0,0 +1,28 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.parser.Node;
public class DefaultLabelStatement extends StatementModel {
public DefaultLabelStatement(StatementOwner owner, Node source) {
super(owner, source);
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Return (nothing)");
}
@Override
public int resolveExpressions() {
return 0;
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
}
}

View File

@@ -0,0 +1,99 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.bytecode.TypeSignature;
import slangc.model.ExpressionModel;
import slangc.model.ExpressionOwner;
import slangc.model.InnerTypeScope;
import slangc.model.MemberModel;
import slangc.model.Named;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.parser.Branch;
import slangc.parser.Node;
public class DoWhileStatement extends StatementModel implements StatementOwner, ExpressionOwner {
private StatementModel innerStatement;
private ExpressionModel condition;
public DoWhileStatement(StatementOwner owner, Branch source) {
super(owner, source);
innerStatement = StatementModel.construct(this, source.getSubnode(1));
condition = ExpressionModel.construct(this, source.getSubnode(3));
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Do While:");
condition.dump(reporter, indent + incr, incr);
innerStatement.dump(reporter, indent + incr, incr);
}
//@Override
public TypeModel resolveType(Node subnode) {
return getOwner().resolveType(subnode);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner().getTypeScope();
}
//@Override
public TypeModel getExpectedResult(ExpressionModel e) {
// TODO Should probably be boolean
return null;
}
@Override
public Named lookupSimpleName(String name) {
return getOwner().lookupSimpleName(name);
}
public MethodModel[] lookupSimpleMethod(String name) {
// TODO: Better interface support
return super.lookupSimpleMethod(name);
}
@Override
public int resolveExpressions() {
return innerStatement.resolveExpressions() + condition.resolveExpressions();
}
public ExpressionModel getCondition() {
return condition;
}
public StatementModel getInnerStatement() {
return innerStatement;
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
BytecodeInstructionWriter.Label beginLabel = w.newLabel("dowhile_begin");
BytecodeInstructionWriter.Label condLabel = w.newLabel("dowhile_cond");
BytecodeInstructionWriter.Label endLabel = w.newLabel("dowhile_end");
w.pushContinue(condLabel);
w.pushBreak(endLabel);
w.labelHere(beginLabel);
getInnerStatement().generate(w);
w.labelHere(condLabel);
TypeSignature xt = getCondition().generate(w);
w.genJump(BytecodeInstructionWriter.JumpOp.IFTRUE, beginLabel);
w.labelHere(endLabel);
w.popBreak(endLabel);
w.popContinue(condLabel);
}
}

View File

@@ -0,0 +1,29 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.parser.Node;
public class EmptyStatement extends StatementModel {
public EmptyStatement(StatementOwner owner, Node source) {
super(owner, source);
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Empty statement (just a semicolon?)");
}
@Override
public int resolveExpressions() {
return 0;
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
// Nothing to generate.
}
}

View File

@@ -0,0 +1,79 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.bytecode.TypeSignature;
import slangc.model.ExpressionModel;
import slangc.model.ExpressionOwner;
import slangc.model.InnerTypeScope;
import slangc.model.MemberModel;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.parser.Branch;
import slangc.parser.Node;
public class ExpressionStatement extends StatementModel implements ExpressionOwner {
private ExpressionModel expression;
public ExpressionStatement(StatementOwner owner, Branch source) {
super(owner, source);
expression = ExpressionModel.construct(this, source.getSubnode(0));
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Expression (result discarded):");
expression.dump(reporter, indent + incr, incr);
}
public ExpressionModel getExpression() {
return expression;
}
//@Override
public TypeModel getExpectedResult(ExpressionModel e) {
// Result is discarded so type is unimportant
return null;
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner().getTypeScope();
}
//@Override
public TypeModel resolveType(Node subnode) {
return getOwner().resolveType(subnode);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
@Override
public int resolveExpressions() {
return expression.resolveExpressions();
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
TypeSignature gend = getExpression().generate(w);
if (!gend.mappableEquals(TypeSignature.VOID)) {
w.genDrop(gend);
}
}
public MethodModel[] lookupSimpleMethod(String name) {
// TODO: Better interface support
return super.lookupSimpleMethod(name);
}
public slangc.model.Named lookupSimpleName(String name) {
// TODO: Better interface support
return super.lookupSimpleName(name);
}
}

View File

@@ -0,0 +1,139 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.bytecode.TypeSignature;
import slangc.model.ClauseModel;
import slangc.model.ExpressionModel;
import slangc.model.ExpressionOwner;
import slangc.model.InnerTypeScope;
import slangc.model.LocalVariableSlot;
import slangc.model.MemberModel;
import slangc.model.Named;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.model.clauses.Expressions;
import slangc.model.clauses.ExpressionsOrVariables;
import slangc.model.clauses.Variables;
import slangc.parser.Branch;
import slangc.parser.Node;
public class ForStatement extends StatementModel implements StatementOwner, ExpressionOwner {
private ExpressionsOrVariables initials;
private Expressions conditions; // Note: should probably contain exactly 0 or 1 expressions!
private Expressions increments;
private StatementModel innerStatement;
public ForStatement(StatementOwner owner, Branch source) {
super(owner, source);
initials = (ExpressionsOrVariables) ClauseModel.construct(this, (Branch) source.getSubnode(2));
conditions = (Expressions) ClauseModel.construct(this, (Branch) source.getSubnode(4));
increments = (Expressions) ClauseModel.construct(this, (Branch) source.getSubnode(6));
innerStatement = StatementModel.construct(this, source.getSubnode(8));
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> For:");
initials.dump(reporter, indent + incr, incr);
conditions.dump(reporter, indent + incr, incr);
increments.dump(reporter, indent + incr, incr);
innerStatement.dump(reporter, indent + incr, incr);
}
@Override
public int resolveExpressions() {
return initials.resolveExpressions()
+ conditions.resolveExpressions()
+ increments.resolveExpressions()
+ innerStatement.resolveExpressions();
}
//@Override
public TypeModel resolveType(Node subnode) {
return getOwner().resolveType(subnode);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner().getTypeScope();
}
//@Override
public TypeModel getExpectedResult(ExpressionModel e) {
// TODO Auto-generated method stub
return null;
}
@Override
public Named lookupSimpleName(String name) {
if (initials instanceof Variables) {
Variables vars = (Variables) initials;
if (vars.hasVariable(name)) {
return vars.getVariable(name);
}
}
return super.lookupSimpleName(name);
}
public MethodModel[] lookupSimpleMethod(String name) {
// TODO: Better interface support
return super.lookupSimpleMethod(name);
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
BytecodeInstructionWriter.Label beginLabel = w.newLabel("for_begin");
BytecodeInstructionWriter.Label endLabel = w.newLabel("for_end");
w.pushContinue(beginLabel);
w.pushBreak(endLabel);
if (initials instanceof Expressions) {
for (int i = 0; i < ((Expressions)initials).countExpressions(); i++) {
TypeSignature cr = ((Expressions)initials).getExpression(i).generate(w);
if (!cr.mappableEquals(TypeSignature.VOID)) {
w.genDrop(cr);
}
}
} else {
for (int i = 0; i < ((Variables)initials).countVariables(); i++) {
LocalVariableSlot s = ((Variables)initials).getVariable(i);
w.genDeclareLocal(s.getStorageType().getTypeSignature(), s.getIndex());
}
for (int i = 0; i < ((Variables)initials).countVariables(); i++) {
LocalVariableSlot s = ((Variables)initials).getVariable(i);
if (s.hasInitialiser()) {
s.getInitialiser().generate(w);
w.genStoreLocalOrParam(s.getStorageType().getTypeSignature(), s.getIndex());
}
}
}
w.labelHere(beginLabel);
if (conditions.countExpressions() != 0) {
TypeSignature xt = conditions.getExpression(0).generate(w);
w.genJump(BytecodeInstructionWriter.JumpOp.IFFALSE, endLabel);
}
getInnerStatement().generate(w);
for (int i = 0; i < increments.countExpressions(); i++) {
TypeSignature cr = increments.getExpression(i).generate(w);
if (!cr.mappableEquals(TypeSignature.VOID)) {
w.genDrop(cr);
}
}
w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, beginLabel);
w.labelHere(endLabel);
w.popBreak(endLabel);
w.popContinue(beginLabel);
}
public StatementModel getInnerStatement() {
return innerStatement;
}
}

View File

@@ -0,0 +1,104 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.bytecode.TypeSignature;
import slangc.model.ClauseModel;
import slangc.model.ExpressionModel;
import slangc.model.ExpressionOwner;
import slangc.model.InnerTypeScope;
import slangc.model.MemberModel;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.model.clauses.ElseClause;
import slangc.parser.Branch;
import slangc.parser.Node;
public class IfStatement extends StatementModel implements StatementOwner, ExpressionOwner {
private ExpressionModel condition;
private StatementModel innerStatement;
private ElseClause elseClause;
public IfStatement(StatementOwner owner, Branch source) {
super(owner, source);
condition = ExpressionModel.construct(this, source.getSubnode(1));
innerStatement = StatementModel.construct(this, source.getSubnode(2));
elseClause = (ElseClause)ClauseModel.construct(this, source.getSubnode(3));
}
public MethodModel[] lookupSimpleMethod(String name) {
// TODO: Better interface support
return super.lookupSimpleMethod(name);
}
public slangc.model.Named lookupSimpleName(String name) {
// TODO: Better interface support
return super.lookupSimpleName(name);
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> If:");
condition.dump(reporter, indent + incr, incr);
innerStatement.dump(reporter, indent + incr, incr);
if (elseClause != null) {
elseClause.dump(reporter, indent + incr, incr);
}
}
//@Override
public TypeModel resolveType(Node subnode) {
return getOwner().resolveType(subnode);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner().getTypeScope();
}
//@Override
public TypeModel getExpectedResult(ExpressionModel e) {
// TODO Probably should be boolean
return null;
}
@Override
public int resolveExpressions() {
return condition.resolveExpressions() + innerStatement.resolveExpressions() + (elseClause == null ? 0 : elseClause.resolveExpressions());
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
BytecodeInstructionWriter.Label elseLabel = w.newLabel("if_else");
BytecodeInstructionWriter.Label endLabel = w.newLabel("if_end");
TypeSignature xt = getCondition().generate(w);
w.genJump(BytecodeInstructionWriter.JumpOp.IFFALSE, elseLabel);
getInnerStatement().generate(w);
w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, endLabel);
w.labelHere(elseLabel);
if (getElseClause() != null) {
getElseClause().getInnerStatement().generate(w);
}
w.labelHere(endLabel);
}
public ExpressionModel getCondition() {
return condition;
}
public StatementModel getInnerStatement() {
return innerStatement;
}
public ElseClause getElseClause() {
return elseClause;
}
}

View File

@@ -0,0 +1,78 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.bytecode.TypeSignature;
import slangc.model.ExpressionModel;
import slangc.model.ExpressionOwner;
import slangc.model.InnerTypeScope;
import slangc.model.MemberModel;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.parser.Branch;
import slangc.parser.Node;
public class ReturnExpressionStatement extends StatementModel implements ExpressionOwner {
private ExpressionModel expression;
public ReturnExpressionStatement(StatementOwner owner, Branch source) {
super(owner, source);
expression = ExpressionModel.construct(this, source.getSubnode(1));
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Return expression:");
expression.dump(reporter, indent + incr, incr);
}
public ExpressionModel getExpression() {
return expression;
}
//@Override
public TypeModel getExpectedResult(ExpressionModel e) {
// TODO Could be determined if necessary
return null;
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner().getTypeScope();
}
//@Override
public TypeModel resolveType(Node subnode) {
return getOwner().resolveType(subnode);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
@Override
public int resolveExpressions() {
return expression.resolveExpressions();
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
TypeSignature t = getExpression().generate(w);
w.genValueReturn(t);
}
public MethodModel[] lookupSimpleMethod(String name) {
// TODO: Better interface support
return super.lookupSimpleMethod(name);
}
public slangc.model.Named lookupSimpleName(String name) {
// TODO: Better interface support
return super.lookupSimpleName(name);
}
}

View File

@@ -0,0 +1,29 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.parser.Node;
public class ReturnNothingStatement extends StatementModel {
public ReturnNothingStatement(StatementOwner owner, Node source) {
super(owner, source);
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Return nothing");
}
@Override
public int resolveExpressions() {
return 0;
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
w.genVoidReturn();
}
}

View File

@@ -0,0 +1,173 @@
package slangc.model.statements;
import java.util.ArrayList;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.bytecode.TypeSignature;
import slangc.model.ClauseModel;
import slangc.model.ExpressionModel;
import slangc.model.ExpressionOwner;
import slangc.model.InnerTypeScope;
import slangc.model.MemberModel;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.model.clauses.SwitchMembers;
import slangc.model.expressions.BinaryExpression;
import slangc.parser.Branch;
import slangc.parser.Node;
public class SwitchStatement extends StatementModel implements StatementOwner, ExpressionOwner {
private ExpressionModel condition;
private SwitchMembers innerStatement;
public SwitchStatement(StatementOwner owner, Branch source) {
super(owner, source);
condition = ExpressionModel.construct(this, source.getSubnode(1));
innerStatement = (SwitchMembers) ClauseModel.construct(this, source.getSubnode(3));
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Switch:");
condition.dump(reporter, indent + incr, incr);
innerStatement.dump(reporter, indent + incr, incr);
}
@Override
public int resolveExpressions() {
return condition.resolveExpressions() + innerStatement.resolveExpressions();
}
//@Override
public TypeModel resolveType(Node subnode) {
return getOwner().resolveType(subnode);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner().getTypeScope();
}
//@Override
public TypeModel getExpectedResult(ExpressionModel e) {
// TODO Auto-generated method stub
return null;
}
public int countCaseLabels() {
int nlabels = 0;
for (int i = 0; i < innerStatement.countMembers(); i++) {
StatementModel s = innerStatement.getMember(i);
if (s instanceof CaseLabelStatement) {
nlabels++;
}
}
return nlabels;
}
public CaseLabelStatement[] findCaseLabels() {
CaseLabelStatement[] labels = new CaseLabelStatement[countCaseLabels()];
int labelIndex = 0;
for (int i = 0; i < innerStatement.countMembers(); i++) {
StatementModel s = innerStatement.getMember(i);
if (s instanceof CaseLabelStatement) {
labels[labelIndex] = (CaseLabelStatement)s;
labelIndex++;
}
}
return labels;
}
public DefaultLabelStatement findDefaultLabel() {
for (int i = 0; i < innerStatement.countMembers(); i++) {
StatementModel s = innerStatement.getMember(i);
if (s instanceof DefaultLabelStatement) {
return (DefaultLabelStatement) s;
}
}
return null;
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
BytecodeInstructionWriter.Label defaultLabelA = w.newLabel("switch_defaultA");
BytecodeInstructionWriter.Label defaultLabelB = w.newLabel("switch_defaultB");
BytecodeInstructionWriter.Label endLabel = w.newLabel("switch_end");
BytecodeInstructionWriter.Label[] caseLabelsA = new BytecodeInstructionWriter.Label[countCaseLabels()];
BytecodeInstructionWriter.Label[] caseLabelsB = new BytecodeInstructionWriter.Label[countCaseLabels()];
for (int i = 0; i < caseLabelsA.length; i++) {
caseLabelsA[i] = w.newLabel("switch_casea");
caseLabelsB[i] = w.newLabel("switch_caseb");
}
CaseLabelStatement[] caseLabelStatemtents = findCaseLabels();
DefaultLabelStatement defaultLabelStatement = findDefaultLabel();
w.pushBreak(endLabel);
TypeSignature xt = condition.generate(w);
TypeModel xtm = condition.getResult().getValueType();
for (int i = 0; i < caseLabelStatemtents.length; i++) {
w.genDup(xt);
CaseLabelStatement l = caseLabelStatemtents[i];
TypeSignature cxt = l.getExpression().generate(w);
BinaryExpression.generateALUOp(w, xtm, "==", l.getExpression().getResult().getValueType());
w.genJump(BytecodeInstructionWriter.JumpOp.IFTRUE, caseLabelsA[i]);
}
//w.genDrop(xt);
w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, defaultLabelA);
int currentLabelIndex = 0;
for (int i = 0; i < innerStatement.countMembers(); i++) {
StatementModel s = innerStatement.getMember(i);
if (s instanceof CaseLabelStatement) {
w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, caseLabelsB[currentLabelIndex]);
w.labelHere(caseLabelsA[currentLabelIndex]);
w.genDrop(xt);
w.labelHere(caseLabelsB[currentLabelIndex]);
currentLabelIndex++;
} else if (s instanceof DefaultLabelStatement) {
w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, defaultLabelB);
w.labelHere(defaultLabelA);
w.genDrop(xt);
w.labelHere(defaultLabelB);
} else {
s.generate(w);
}
}
if (defaultLabelStatement == null) {
w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, defaultLabelB);
w.labelHere(defaultLabelA);
w.genDrop(xt);
w.labelHere(defaultLabelB);
}
w.popBreak(endLabel);
w.labelHere(endLabel);
}
/*
public MethodModel[] lookupSimpleMethod(String name) {
// TODO: Better interface support
return super.lookupSimpleMethod(name);
}
public slangc.model.Named lookupSimpleName(String name) {
// TODO: Better interface support
return super.lookupSimpleName(name);
}*/
}

View File

@@ -0,0 +1,86 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.model.ExpressionModel;
import slangc.model.ExpressionOwner;
import slangc.model.InnerTypeScope;
import slangc.model.MemberModel;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.parser.Branch;
import slangc.parser.Node;
public class SynchronizedStatement extends StatementModel implements StatementOwner, ExpressionOwner {
private ExpressionModel condition;
private StatementModel innerStatement;
public SynchronizedStatement(StatementOwner owner, Branch source) {
super(owner, source);
condition = ExpressionModel.construct(this, source.getSubnode(1));
innerStatement = StatementModel.construct(this, source.getSubnode(2));
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Synchronized:");
condition.dump(reporter, indent + incr, incr);
innerStatement.dump(reporter, indent + incr, incr);
}
@Override
public int resolveExpressions() {
return condition.resolveExpressions() + innerStatement.resolveExpressions();
}
//@Override
public TypeModel resolveType(Node subnode) {
return getOwner().resolveType(subnode);
}
public MethodModel[] lookupSimpleMethod(String name) {
// TODO: Better interface support
return super.lookupSimpleMethod(name);
}
public slangc.model.Named lookupSimpleName(String name) {
// TODO: Better interface support
return super.lookupSimpleName(name);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner().getTypeScope();
}
//@Override
public TypeModel getExpectedResult(ExpressionModel e) {
// TODO Should probably be Object or some configurable target
return null;
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
BytecodeInstructionWriter.Label begin = w.newLabel("sync_begin");
BytecodeInstructionWriter.Label catchEnd = w.newLabel("sync_end");
BytecodeInstructionWriter.FinallyLabel fin = w.newFinallyLabel("sync_finally", begin, catchEnd);
condition.generate(w);
w.genLock();
w.labelHere(begin);
innerStatement.generate(w);
w.labelHere(catchEnd);
w.labelHere(fin);
condition.generate(w);
w.genCheckRethrow();
w.genUnlock();
}
}

View File

@@ -0,0 +1,77 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.model.ExpressionModel;
import slangc.model.ExpressionOwner;
import slangc.model.InnerTypeScope;
import slangc.model.MemberModel;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.parser.Branch;
import slangc.parser.Node;
public class ThrowStatement extends StatementModel implements ExpressionOwner {
private ExpressionModel expression;
public ThrowStatement(StatementOwner owner, Branch source) {
super(owner, source);
expression = ExpressionModel.construct(this, source.getSubnode(1));
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Throw:");
expression.dump(reporter, indent + incr, incr);
}
@Override
public int resolveExpressions() {
return expression.resolveExpressions();
}
public ExpressionModel getExpression() {
return expression;
}
//@Override
public TypeModel getExpectedResult(ExpressionModel e) {
// TODO: Should probably be Throwable or some configurable type
return null;
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner().getTypeScope();
}
//@Override
public TypeModel resolveType(Node subnode) {
return getOwner().resolveType(subnode);
}
public MethodModel[] lookupSimpleMethod(String name) {
// TODO: Better interface support
return super.lookupSimpleMethod(name);
}
public slangc.model.Named lookupSimpleName(String name) {
// TODO: Better interface support
return super.lookupSimpleName(name);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
//@Override
public void innerGenerate(BytecodeInstructionWriter w) {
getExpression().generate(w);
w.genThrow();
}
}

View File

@@ -0,0 +1,121 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.model.ClauseModel;
import slangc.model.InnerTypeScope;
import slangc.model.MemberModel;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.model.clauses.CatchClause;
import slangc.model.clauses.FinallyClause;
import slangc.parser.Branch;
import slangc.parser.Node;
public class TryStatement extends StatementModel implements StatementOwner {
private StatementModel innerStatement;
private CatchClause[] catchClauses;
private FinallyClause finallyClause;
public TryStatement(StatementOwner owner, Branch source) {
super(owner, source);
innerStatement = StatementModel.construct(this, source.getSubnode(2));
ClauseModel[] catches = ClauseModel.constructMultiple(this, (Branch)source.getSubnode(3));
catchClauses = new CatchClause[catches.length];
for (int i = 0; i < catches.length; i++) {
catchClauses[i] = (CatchClause)catches[i];
}
finallyClause = (FinallyClause)ClauseModel.construct(this, source.getSubnode(4));
}
//@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Try:");
innerStatement.dump(reporter, indent + incr, incr);
for (int i = 0; i < catchClauses.length; i++) {
catchClauses[i].dump(reporter, indent + incr, incr);
}
if (finallyClause != null) {
finallyClause.dump(reporter, indent + incr, incr);
}
}
//@Override
public int resolveExpressions() {
int nresolved = 0;
nresolved += innerStatement.resolveExpressions();
for (int i = 0; i < catchClauses.length; i++) {
nresolved += catchClauses[i].resolveExpressions();
}
if (finallyClause != null) {
nresolved += finallyClause.resolveExpressions();
}
return nresolved;
}
//@Override
public TypeModel resolveType(Node subnode) {
return getOwner().resolveType(subnode);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner().getTypeScope();
}
public MethodModel[] lookupSimpleMethod(String name) {
// TODO: Better interface support
return super.lookupSimpleMethod(name);
}
public slangc.model.Named lookupSimpleName(String name) {
// TODO: Better interface support
return super.lookupSimpleName(name);
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
BytecodeInstructionWriter.Label begin = w.newLabel("try_begin");
BytecodeInstructionWriter.Label end = w.newLabel("try_end");
BytecodeInstructionWriter.Label catchEnd = w.newLabel("try_catch_end");
BytecodeInstructionWriter.CatchLabel[] catches = new BytecodeInstructionWriter.CatchLabel[catchClauses.length];
BytecodeInstructionWriter.FinallyLabel fin = finallyClause == null ? null : w.newFinallyLabel("try_finally", begin, catchEnd);
for (int i = 0; i < catches.length; i++) {
catches[i] = w.newCatchLabel("try_catch", begin, end, catchClauses[i].getCatchType().getTypeSignature());
}
w.labelHere(begin);
getInnerStatement().generate(w);
w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, catchEnd);
w.labelHere(end);
for (int i = 0; i < catches.length; i++) {
w.labelHere(catches[i]);
// Manually notify the writer that a typeName (the exception) has been pushed
w.vpush(catchClauses[i].getCatchType().getTypeSignature());
// Now we just need to store it to our variable so it can be accessed normally
// It needs to be declared first, but in practice a backend may just ignore this declaration
w.genDeclareLocal(catchClauses[i].getCatchVariable().getStorageType().getTypeSignature(), catchClauses[i].getCatchVariable().getIndex());
w.genStoreLocalOrParam(catchClauses[i].getCatchVariable().getStorageType().getTypeSignature(), catchClauses[i].getCatchVariable().getIndex());
catchClauses[i].getInnerStatement().generate(w);
w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, catchEnd);
}
w.labelHere(catchEnd);
if (finallyClause != null) {
w.labelHere(fin);
finallyClause.getInnerStatement().generate(w);
w.genCheckRethrow();
}
}
public StatementModel getInnerStatement() {
return innerStatement;
}
}

View File

@@ -0,0 +1,47 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.model.UserTypeModel;
import slangc.parser.Branch;
import slangc.parser.ErrorType;
import slangc.parser.Node;
public class TypeDeclarationStatement extends StatementModel {
TypeModel declaredType;
public TypeDeclarationStatement(StatementOwner owner, Node source) {
super(owner, source);
declaredType = getOwner().getTypeScope().getInnerTypeForSource((Branch)source);
if (declaredType == null) {
source.annotate(ErrorType.INTERNAL_ERROR, "Unable to match statement to type declaration");
}
if (declaredType instanceof UserTypeModel) {
((UserTypeModel)declaredType).statementOrExpression = this;
}
//sourceFile.annotate(WarningType.INTERNAL_WARNING, "Named type declarations in statement context are not fully handled yet");
}
@Override
public int resolveExpressions() {
return 0;
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Type declaration statement for " + getDeclaredType());
}
public TypeModel getDeclaredType() {
return declaredType;
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
w.genError("TODO: innerGenerate for " + Type.of(this));
}
}

View File

@@ -0,0 +1,32 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.parser.ErrorType;
import slangc.parser.Node;
public class UnrecognisedStatement extends StatementModel {
public UnrecognisedStatement(StatementOwner owner, Node source) {
super(owner, source);
//throw new Error("Unrecognised statement type " + sourceFile.getNodeType() + " (Internal error/TODO)");
source.annotate(ErrorType.INTERNAL_ERROR, "Unrecognised statement type " + source.getNodeType() + " (Internal error/TODO)");
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> TODO: Unrecognised statement (" + getSource().getNodeType() + ")");
}
@Override
public int resolveExpressions() {
return 0;
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
w.genError("TODO: innerGenerate for " + Type.of(this));
}
}

View File

@@ -0,0 +1,107 @@
package slangc.model.statements;
import slang.data.List;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.bytecode.TypeSignature;
import slangc.model.InnerTypeScope;
import slangc.model.LocalVariableSlot;
import slangc.model.MemberModel;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.parser.Branch;
import slangc.parser.Node;
public class VariableStatement extends StatementModel implements StatementOwner {
private TypeModel type;
private List<LocalVariableSlot> slots = new List<LocalVariableSlot>();
public VariableStatement(StatementOwner owner, Branch source) {
super(owner, source);
type = owner.resolveType(source.getSubnode(1));
Branch l = (Branch) source.getSubnode(2);
for (int i = 0; i < l.countSubnodes(); i++) {
slots.append(new LocalVariableSlot(this, (Branch)l.getSubnode(i), type));
}
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> Variable statement:");
// do not recurse: type.dump(reporter, indent + incr, incr);
for (int i = 0; i < slots.count(); i++) {
slots.get(i).dump(reporter, indent + incr, incr);
}
}
@Override
public int resolveExpressions() {
int nresolved = 0;
for (int i = 0; i < slots.count(); i++) {
nresolved += slots.get(i).resolveExpressions();
}
return nresolved;
}
public boolean hasVariable(String name) {
for (int i = 0; i < slots.count(); i++) {
if (slots.get(i).getName().equals(name)) {
return true;
}
}
return false;
}
public LocalVariableSlot getVariable(String name) {
for (int i = 0; i < slots.count(); i++) {
if (slots.get(i).getName().equals(name)) {
return slots.get(i);
}
}
return null;
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner().getTypeScope();
}
//@Override
public TypeModel resolveType(Node subnode) {
return getOwner().resolveType(subnode);
}
public MethodModel[] lookupSimpleMethod(String name) {
// TODO: Better interface support
return super.lookupSimpleMethod(name);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
// The first pass declares each of the variables (this will reset them to default values)
for (int i = 0; i < slots.count(); i++) {
LocalVariableSlot s = slots.get(i);
w.genDeclareLocal(s.getStorageType().getTypeSignature(), s.getIndex());
}
// The second pass generates any initialisers
for (int i = 0; i < slots.count(); i++) {
LocalVariableSlot s = slots.get(i);
if (s.hasInitialiser()) {
TypeSignature storing = s.getInitialiser().generate(w);
if (!storing.mappableEquals(s.getInitialiser().getResult().getValueTypeWithNullType(s.getStorageType()).getTypeSignature())) {
w.genConvert(storing, s.getStorageType().getTypeSignature());
storing = s.getStorageType().getTypeSignature();
}
w.genStoreLocalOrParam(s.getStorageType().getTypeSignature(), s.getIndex());
}
}
}
}

View File

@@ -0,0 +1,95 @@
package slangc.model.statements;
import slangc.api.BytecodeInstructionWriter;
import slangc.api.Reporter;
import slangc.bytecode.TypeSignature;
import slangc.model.ExpressionModel;
import slangc.model.ExpressionOwner;
import slangc.model.InnerTypeScope;
import slangc.model.MemberModel;
import slangc.model.StatementModel;
import slangc.model.StatementOwner;
import slangc.model.TypeModel;
import slangc.parser.Branch;
import slangc.parser.Node;
public class WhileStatement extends StatementModel implements StatementOwner, ExpressionOwner {
private ExpressionModel condition;
private StatementModel innerStatement;
public WhileStatement(StatementOwner owner, Branch source) {
super(owner, source);
condition = ExpressionModel.construct(this, source.getSubnode(1));
innerStatement = StatementModel.construct(this, source.getSubnode(2));
}
@Override
public void dump(Reporter reporter, String indent, String incr) {
reporter.note("DUMP", indent + "> While:");
condition.dump(reporter, indent + incr, incr);
innerStatement.dump(reporter, indent + incr, incr);
}
@Override
public int resolveExpressions() {
return condition.resolveExpressions() + innerStatement.resolveExpressions();
}
//@Override
public TypeModel resolveType(Node subnode) {
return getOwner().resolveType(subnode);
}
public MethodModel[] lookupSimpleMethod(String name) {
// TODO: Better interface support
return super.lookupSimpleMethod(name);
}
public slangc.model.Named lookupSimpleName(String name) {
// TODO: Better interface support
return super.lookupSimpleName(name);
}
//@Override
public MemberModel getMethodOrField() {
return getOwner().getMethodOrField();
}
//@Override
public InnerTypeScope getTypeScope() {
return getOwner().getTypeScope();
}
//@Override
public TypeModel getExpectedResult(ExpressionModel e) {
// TODO Should probably be boolean
return null;
}
public ExpressionModel getCondition() {
return condition;
}
public StatementModel getInnerStatement() {
return innerStatement;
}
@Override
public void innerGenerate(BytecodeInstructionWriter w) {
BytecodeInstructionWriter.Label beginLabel = w.newLabel("while_begin");
BytecodeInstructionWriter.Label endLabel = w.newLabel("while_end");
w.pushContinue(beginLabel);
w.pushBreak(endLabel);
w.labelHere(beginLabel);
TypeSignature xt = getCondition().generate(w);
w.genJump(BytecodeInstructionWriter.JumpOp.IFFALSE, endLabel);
getInnerStatement().generate(w);
w.genJump(BytecodeInstructionWriter.JumpOp.GOTO, beginLabel);
w.labelHere(endLabel);
w.popBreak(endLabel);
w.popContinue(beginLabel);
}
}