Initial commit of main compiler sources (or should I say ... SAUCES!)
This commit is contained in:
68
slangc/model/statements/AssertStatement.sauce
Normal file
68
slangc/model/statements/AssertStatement.sauce
Normal 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();
|
||||
}
|
||||
}
|
109
slangc/model/statements/BlockStatement.sauce
Normal file
109
slangc/model/statements/BlockStatement.sauce
Normal 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);
|
||||
}
|
||||
}
|
33
slangc/model/statements/BreakStatement.sauce
Normal file
33
slangc/model/statements/BreakStatement.sauce
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
77
slangc/model/statements/CaseLabelStatement.sauce
Normal file
77
slangc/model/statements/CaseLabelStatement.sauce
Normal 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);
|
||||
}
|
||||
}
|
33
slangc/model/statements/ContinueStatement.sauce
Normal file
33
slangc/model/statements/ContinueStatement.sauce
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
28
slangc/model/statements/DefaultLabelStatement.sauce
Normal file
28
slangc/model/statements/DefaultLabelStatement.sauce
Normal 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) {
|
||||
}
|
||||
}
|
99
slangc/model/statements/DoWhileStatement.sauce
Normal file
99
slangc/model/statements/DoWhileStatement.sauce
Normal 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);
|
||||
}
|
||||
|
||||
}
|
29
slangc/model/statements/EmptyStatement.sauce
Normal file
29
slangc/model/statements/EmptyStatement.sauce
Normal 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.
|
||||
}
|
||||
}
|
79
slangc/model/statements/ExpressionStatement.sauce
Normal file
79
slangc/model/statements/ExpressionStatement.sauce
Normal 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);
|
||||
}
|
||||
}
|
139
slangc/model/statements/ForStatement.sauce
Normal file
139
slangc/model/statements/ForStatement.sauce
Normal 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;
|
||||
}
|
||||
}
|
104
slangc/model/statements/IfStatement.sauce
Normal file
104
slangc/model/statements/IfStatement.sauce
Normal 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;
|
||||
}
|
||||
}
|
78
slangc/model/statements/ReturnExpressionStatement.sauce
Normal file
78
slangc/model/statements/ReturnExpressionStatement.sauce
Normal 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);
|
||||
}
|
||||
}
|
29
slangc/model/statements/ReturnNothingStatement.sauce
Normal file
29
slangc/model/statements/ReturnNothingStatement.sauce
Normal 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();
|
||||
}
|
||||
}
|
173
slangc/model/statements/SwitchStatement.sauce
Normal file
173
slangc/model/statements/SwitchStatement.sauce
Normal 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);
|
||||
}*/
|
||||
}
|
86
slangc/model/statements/SynchronizedStatement.sauce
Normal file
86
slangc/model/statements/SynchronizedStatement.sauce
Normal 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();
|
||||
}
|
||||
}
|
77
slangc/model/statements/ThrowStatement.sauce
Normal file
77
slangc/model/statements/ThrowStatement.sauce
Normal 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();
|
||||
}
|
||||
}
|
121
slangc/model/statements/TryStatement.sauce
Normal file
121
slangc/model/statements/TryStatement.sauce
Normal 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;
|
||||
}
|
||||
}
|
47
slangc/model/statements/TypeDeclarationStatement.sauce
Normal file
47
slangc/model/statements/TypeDeclarationStatement.sauce
Normal 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));
|
||||
}
|
||||
}
|
32
slangc/model/statements/UnrecognisedStatement.sauce
Normal file
32
slangc/model/statements/UnrecognisedStatement.sauce
Normal 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));
|
||||
}
|
||||
}
|
107
slangc/model/statements/VariableStatement.sauce
Normal file
107
slangc/model/statements/VariableStatement.sauce
Normal 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
95
slangc/model/statements/WhileStatement.sauce
Normal file
95
slangc/model/statements/WhileStatement.sauce
Normal 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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user