Skip to content

Commit

Permalink
Refactor Parser to be less mutable
Browse files Browse the repository at this point in the history
- move ClassGenerationContext into it
- make MethodGenerationContext more immutable by preferring constructor over setters
- let assemble do the right thing without external check of flag

Signed-off-by: Stefan Marr <[email protected]>
  • Loading branch information
smarr committed Mar 17, 2020
1 parent 8a9ab3c commit bf7fc34
Show file tree
Hide file tree
Showing 4 changed files with 57 additions and 46 deletions.
4 changes: 2 additions & 2 deletions src/som/compiler/ClassGenerationContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ public void addInstanceMethod(final som.vmobjects.SInvokable meth) {
instanceMethods.add(meth);
}

public void setClassSide(boolean b) {
classSide = b;
public void startClassSide() {
classSide = true;
}

public void addClassMethod(final som.vmobjects.SInvokable meth) {
Expand Down
46 changes: 34 additions & 12 deletions src/som/compiler/MethodGenerationContext.java
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,22 @@

package som.compiler;

import static som.interpreter.Bytecodes.*;
import static som.interpreter.Bytecodes.DUP;
import static som.interpreter.Bytecodes.HALT;
import static som.interpreter.Bytecodes.POP;
import static som.interpreter.Bytecodes.POP_ARGUMENT;
import static som.interpreter.Bytecodes.POP_FIELD;
import static som.interpreter.Bytecodes.POP_LOCAL;
import static som.interpreter.Bytecodes.PUSH_ARGUMENT;
import static som.interpreter.Bytecodes.PUSH_BLOCK;
import static som.interpreter.Bytecodes.PUSH_CONSTANT;
import static som.interpreter.Bytecodes.PUSH_FIELD;
import static som.interpreter.Bytecodes.PUSH_GLOBAL;
import static som.interpreter.Bytecodes.PUSH_LOCAL;
import static som.interpreter.Bytecodes.RETURN_LOCAL;
import static som.interpreter.Bytecodes.RETURN_NON_LOCAL;
import static som.interpreter.Bytecodes.SEND;
import static som.interpreter.Bytecodes.SUPER_SEND;

import java.util.ArrayList;
import java.util.List;
Expand All @@ -41,8 +56,9 @@

public class MethodGenerationContext {

private ClassGenerationContext holderGenc;
private MethodGenerationContext outerGenc;
private final ClassGenerationContext holderGenc;
private final MethodGenerationContext outerGenc;

private boolean blockMethod;
private SSymbol signature;
private final List<String> arguments = new ArrayList<String>();
Expand All @@ -52,8 +68,14 @@ public class MethodGenerationContext {
private boolean finished;
private final Vector<Byte> bytecode = new Vector<Byte>();

public void setHolder(final ClassGenerationContext cgenc) {
holderGenc = cgenc;
public MethodGenerationContext(final ClassGenerationContext holderGenc,
final MethodGenerationContext outerGenc) {
this.holderGenc = holderGenc;
this.outerGenc = outerGenc;
}

public MethodGenerationContext(final ClassGenerationContext holderGenc) {
this(holderGenc, null);
}

public void addArgument(final String arg) {
Expand All @@ -64,11 +86,15 @@ public boolean isPrimitive() {
return primitive;
}

public SInvokable assemblePrimitive(final Universe universe) {
return SPrimitive.getEmptyPrimitive(signature.getEmbeddedString(), universe);
public SInvokable assemble(final Universe universe) {
if (primitive) {
return SPrimitive.getEmptyPrimitive(signature.getEmbeddedString(), universe);
} else {
return assembleMethod(universe);
}
}

public SMethod assemble(final Universe universe) {
public SMethod assembleMethod(final Universe universe) {
// create a method instance with the given number of bytecodes and
// literals
int numLiterals = literals.size();
Expand Down Expand Up @@ -223,10 +249,6 @@ public ClassGenerationContext getHolder() {
return holderGenc;
}

public void setOuter(final MethodGenerationContext mgenc) {
outerGenc = mgenc;
}

public byte addLiteral(final SAbstractObject lit) {
int i = literals.size();
assert i < 128;
Expand Down
50 changes: 20 additions & 30 deletions src/som/compiler/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,9 @@

public class Parser {

private final Universe universe;
private final String filename;
private final Universe universe;
private final String filename;
private final ClassGenerationContext cgenc;

private final Lexer lexer;
private final BytecodeGenerator bcGen;
Expand Down Expand Up @@ -178,6 +179,7 @@ public String toString() {
public Parser(final Reader reader, final Universe universe, final String filename) {
this.universe = universe;
this.filename = filename;
this.cgenc = new ClassGenerationContext(universe);

sym = NONE;
lexer = new Lexer(reader);
Expand All @@ -186,52 +188,42 @@ public Parser(final Reader reader, final Universe universe, final String filenam
getSymbolFromLexer();
}

public void classdef(final ClassGenerationContext cgenc) throws ProgramDefinitionError {
public ClassGenerationContext classdef() throws ProgramDefinitionError {
cgenc.setName(universe.symbolFor(text));
expect(Identifier);
expect(Equal);

superclass(cgenc);
superclass();

expect(NewTerm);
instanceFields(cgenc);
instanceFields();
while (sym == Identifier || sym == Keyword || sym == OperatorSequence
|| symIn(binaryOpSyms)) {
MethodGenerationContext mgenc = new MethodGenerationContext();
mgenc.setHolder(cgenc);
MethodGenerationContext mgenc = new MethodGenerationContext(cgenc);
mgenc.addArgument("self");

method(mgenc);

if (mgenc.isPrimitive()) {
cgenc.addInstanceMethod(mgenc.assemblePrimitive(universe));
} else {
cgenc.addInstanceMethod(mgenc.assemble(universe));
}
cgenc.addInstanceMethod(mgenc.assemble(universe));
}

if (accept(Separator)) {
cgenc.setClassSide(true);
classFields(cgenc);
cgenc.startClassSide();
classFields();
while (sym == Identifier || sym == Keyword || sym == OperatorSequence
|| symIn(binaryOpSyms)) {
MethodGenerationContext mgenc = new MethodGenerationContext();
mgenc.setHolder(cgenc);
MethodGenerationContext mgenc = new MethodGenerationContext(cgenc);
mgenc.addArgument("self");

method(mgenc);

if (mgenc.isPrimitive()) {
cgenc.addClassMethod(mgenc.assemblePrimitive(universe));
} else {
cgenc.addClassMethod(mgenc.assemble(universe));
}
cgenc.addClassMethod(mgenc.assemble(universe));
}
}
expect(EndTerm);

return cgenc;
}

private void superclass(final ClassGenerationContext cgenc) throws ProgramDefinitionError {
private void superclass() throws ProgramDefinitionError {
SSymbol superName;
if (sym == Identifier) {
superName = universe.symbolFor(text);
Expand Down Expand Up @@ -306,7 +298,7 @@ private boolean expectOneOf(final List<Symbol> ss) {
throw new IllegalStateException(err.toString());
}

private void instanceFields(final ClassGenerationContext cgenc) {
private void instanceFields() {
if (accept(Or)) {
while (sym == Identifier) {
String var = variable();
Expand All @@ -316,7 +308,7 @@ private void instanceFields(final ClassGenerationContext cgenc) {
}
}

private void classFields(final ClassGenerationContext cgenc) {
private void classFields() {
if (accept(Or)) {
while (sym == Identifier) {
String var = variable();
Expand Down Expand Up @@ -564,14 +556,12 @@ private void primary(final MethodGenerationContext mgenc, final Single<Boolean>
nestedTerm(mgenc);
break;
case NewBlock: {
MethodGenerationContext bgenc = new MethodGenerationContext();
MethodGenerationContext bgenc = new MethodGenerationContext(mgenc.getHolder(), mgenc);
bgenc.setIsBlockMethod(true);
bgenc.setHolder(mgenc.getHolder());
bgenc.setOuter(mgenc);

nestedBlock(bgenc);

SMethod blockMethod = bgenc.assemble(universe);
SMethod blockMethod = bgenc.assembleMethod(universe);
mgenc.addLiteral(blockMethod);
bcGen.emitPUSHBLOCK(mgenc, blockMethod);
break;
Expand Down
3 changes: 1 addition & 2 deletions src/som/compiler/SourcecodeCompiler.java
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,9 @@ private som.vmobjects.SClass compileClassString(final String stream,

private som.vmobjects.SClass compile(final som.vmobjects.SClass systemClass,
final Universe universe) throws ProgramDefinitionError {
ClassGenerationContext cgc = new ClassGenerationContext(universe);

som.vmobjects.SClass result = systemClass;
parser.classdef(cgc);
ClassGenerationContext cgc = parser.classdef();

if (systemClass == null) {
result = cgc.assemble();
Expand Down

0 comments on commit bf7fc34

Please sign in to comment.