From 9811e48039367a39149ea9852b8bc460c4a62cad Mon Sep 17 00:00:00 2001 From: jespergravgaard Date: Sun, 22 Dec 2019 22:04:30 +0100 Subject: [PATCH] VariableBuilder has replaced VariableBuilderContext. --- .../kickc/model/VariableBuilder.java | 51 ++++++-- .../kickc/model/VariableBuilderContext.java | 110 ------------------ .../kickc/model/symbols/Procedure.java | 1 - .../kickc/model/symbols/Variable.java | 2 +- .../Pass0GenerateStatementSequence.java | 93 ++++----------- 5 files changed, 68 insertions(+), 189 deletions(-) delete mode 100644 src/main/java/dk/camelot64/kickc/model/VariableBuilderContext.java diff --git a/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java b/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java index 82b5e56c8..abd85ba95 100644 --- a/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java +++ b/src/main/java/dk/camelot64/kickc/model/VariableBuilder.java @@ -15,6 +15,9 @@ import java.util.List; */ public class VariableBuilder { + /** The variable name. */ + private String varName; + /** The scope of the variable. */ private Scope scope; @@ -30,12 +33,46 @@ public class VariableBuilder { /** The directives of the variable declaration. */ private List directives; - public VariableBuilder(Scope scope, boolean isParameter, SymbolType type, ArraySpec arraySpec, List directives) { + /** The data segment. */ + private String dataSegment; + + public VariableBuilder(String varName, Scope scope, boolean isParameter, SymbolType type, ArraySpec arraySpec, List directives, String dataSegment) { + this.varName = varName; this.scope = scope; this.isParameter = isParameter; this.type = type; this.arraySpec = arraySpec; this.directives = directives; + this.dataSegment = dataSegment; + } + + /** + * Build the variable with the properties derived from type, scope, directives and configuration. + * @return The variable + */ + public Variable build() { + Variable variable; + if(isConstant()) { + variable = Variable.createConstant(varName, type, scope, arraySpec, null, dataSegment); + } else if(this.isSingleStaticAssignment()) { + // Create single-static-assignment PHI-master variable + variable = Variable.createPhiMaster(varName, type, scope, getMemoryArea(), dataSegment); + } else { + // Create multiple-assignment variable + variable = Variable.createLoadStore(varName, type, scope, getMemoryArea(), dataSegment); + } + variable.setDeclaredConst(this.isConstant()); + variable.setDeclaredVolatile(this.isVolatile()); + variable.setDeclaredExport(this.isExport()); + variable.setDeclaredAsRegister(this.isOptimize()); + variable.setDeclaredRegister(this.getRegister()); + if(variable.getDeclaredRegister() instanceof Registers.RegisterMainMem) { + ((Registers.RegisterMainMem) variable.getDeclaredRegister()).setVariableRef(variable.getVariableRef()); + } + variable.setMemoryArea(this.getMemoryArea()); + variable.setDeclaredAlignment(this.getAlignment()); + scope.add(variable); + return variable; } /** @@ -174,7 +211,8 @@ public class VariableBuilder { return hasDirective(Directive.ToConst.class); } - /** Declared as export (__export keyword) + /** + * Declared as export (__export keyword) * * @return true if declared as export */ @@ -243,13 +281,14 @@ public class VariableBuilder { /** * Get any memory-alignment of the variables data - * @return + * + * @return The memory alignment */ public Integer getAlignment() { Directive.Align alignDirective = findDirective(Directive.Align.class); if(alignDirective != null) { if(isArray()) { - return alignDirective.alignment; + return alignDirective.alignment; } else { // TODO: Add information about which variable (name) and the offending source line throw new CompileError("Error! Cannot align variable that is not an array."); @@ -294,11 +333,10 @@ public class VariableBuilder { * Examines whether a specific directive is present in the source * * @param directiveClass The class of the type to look for - * @param directives The list of directives to search * @param The class of the type to look for * @return true if the directive if found. false otherwise. */ - private boolean hasDirective(Class directiveClass) { + public boolean hasDirective(Class directiveClass) { return findDirective(directiveClass) != null; } @@ -306,7 +344,6 @@ public class VariableBuilder { * Look for a specific directive type in a list of directives * * @param directiveClass The class of the type to look for - * @param directives The list of directives to search * @param The class of the type to look for * @return The directive if found. null if not found. */ diff --git a/src/main/java/dk/camelot64/kickc/model/VariableBuilderContext.java b/src/main/java/dk/camelot64/kickc/model/VariableBuilderContext.java deleted file mode 100644 index 186170bd2..000000000 --- a/src/main/java/dk/camelot64/kickc/model/VariableBuilderContext.java +++ /dev/null @@ -1,110 +0,0 @@ -package dk.camelot64.kickc.model; - -import dk.camelot64.kickc.model.statements.StatementSource; -import dk.camelot64.kickc.model.symbols.Variable; -import dk.camelot64.kickc.model.values.VariableRef; - -import java.util.List; - -/** - * Used for creating {@link Variable}s with the right properties based on all their directives - */ -public class VariableBuilderContext { - - public VariableBuilderContext() { - } - - /** - * Applies directives to a variable. - * - * @param lValue The variable to apply directives to - * @param sourceDirectives The directives found in the source code - * @param source The source line (for exceptions) - */ - public void applyDirectives(Variable lValue, boolean isParameter, boolean isArray, List sourceDirectives, StatementSource source) { - if(hasDirective(Directive.Const.class, sourceDirectives)) - lValue.setDeclaredConst(true); - if(isArray) - lValue.setDeclaredConst(true); - if(hasDirective(Directive.Volatile.class, sourceDirectives)) - lValue.setDeclaredVolatile(true); - if(hasDirective(Directive.Export.class, sourceDirectives)) - lValue.setDeclaredExport(true); - if(hasDirective(Directive.Register.class, sourceDirectives)) { - lValue.setMemoryArea(Variable.MemoryArea.ZEROPAGE_MEMORY); - lValue.setDeclaredAsRegister(true); - } - if(isArray) - lValue.setMemoryArea(Variable.MemoryArea.MAIN_MEMORY); - if(hasDirective(Directive.MemZp.class, sourceDirectives)) - lValue.setMemoryArea(Variable.MemoryArea.ZEROPAGE_MEMORY); - if(hasDirective(Directive.MemMain.class, sourceDirectives)) - lValue.setMemoryArea(Variable.MemoryArea.MAIN_MEMORY); - Directive.Address addressDirective = findDirective(Directive.Address.class, sourceDirectives); - if(addressDirective != null) { - Variable.MemoryArea memoryArea = (addressDirective.address < 0x100) ? Variable.MemoryArea.ZEROPAGE_MEMORY : Variable.MemoryArea.MAIN_MEMORY; - if(Variable.MemoryArea.ZEROPAGE_MEMORY.equals(memoryArea)) { - lValue.setMemoryArea(Variable.MemoryArea.ZEROPAGE_MEMORY); - Registers.Register register = new Registers.RegisterZpMem(addressDirective.address.intValue(), -1, true); - lValue.setDeclaredRegister(register); - } else { - lValue.setMemoryArea(Variable.MemoryArea.MAIN_MEMORY); - Registers.Register register = new Registers.RegisterMainMem((VariableRef) lValue.getRef(), -1, addressDirective.address); - lValue.setDeclaredRegister(register); - } - } - - Directive.NamedRegister registerDirective = findDirective(Directive.NamedRegister.class, sourceDirectives); - if(registerDirective != null) { - lValue.setDeclaredAsRegister(true); - Registers.Register register = Registers.getRegister(registerDirective.name); - if(register == null) { - throw new CompileError("Error! Unknown register " + registerDirective.name, source); - } - lValue.setDeclaredRegister(register); - } - - Directive.Align alignDirective = findDirective(Directive.Align.class, sourceDirectives); - if(alignDirective != null) { - if(isArray) { - lValue.setDeclaredAlignment(alignDirective.alignment); - } else { - throw new CompileError("Error! Cannot align variable that is not a string or an array " + lValue.toString(), source); - } - } - // TODO: Add strategy for selecting main memory for non-pointer local variables - } - - /** - * Examines whether a specific directive is present in the source - * - * @param directiveClass The class of the type to look for - * @param directives The list of directives to search - * @param The class of the type to look for - * @return true if the directive if found. false otherwise. - */ - private boolean hasDirective(Class directiveClass, List directives) { - return findDirective(directiveClass, directives) != null; - } - - - /** - * Look for a specific directive type in a list of directives - * - * @param directiveClass The class of the type to look for - * @param directives The list of directives to search - * @param The class of the type to look for - * @return The directive if found. null if not found. - */ - private DirectiveClass findDirective(Class directiveClass, List directives) { - if(directives == null) return null; - for(Directive directive : directives) { - if(directiveClass.isInstance(directive)) { - return (DirectiveClass) directive; - } - } - // Not found! - return null; - } - -} diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/Procedure.java b/src/main/java/dk/camelot64/kickc/model/symbols/Procedure.java index af76340fc..c1b59cd10 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Procedure.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Procedure.java @@ -103,7 +103,6 @@ public class Procedure extends Scope { public void setParameters(List parameters) { this.parameterNames = new ArrayList<>(); for(Variable parameter : parameters) { - add(parameter); parameterNames.add(parameter.getLocalName()); } } diff --git a/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java b/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java index 8f9069746..b40c1f931 100644 --- a/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java +++ b/src/main/java/dk/camelot64/kickc/model/symbols/Variable.java @@ -125,9 +125,9 @@ public class Variable implements Symbol { this.type = type; this.scope = scope; this.arraySpec = arraySpec; - this.initValue = initValue; this.dataSegment = dataSegment; this.memoryArea = memoryArea; + this.initValue = initValue; this.comments = new ArrayList<>(); setFullName(); } diff --git a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java index 3cf7eaead..eb15298cd 100644 --- a/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java +++ b/src/main/java/dk/camelot64/kickc/passes/Pass0GenerateStatementSequence.java @@ -47,8 +47,6 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor scopeStack; /** The memory area used by default for variables. */ private Variable.MemoryArea defaultMemoryArea; - /** Context used for adding directives to variables. */ - private VariableBuilderContext directiveContext; public Pass0GenerateStatementSequence(CParser cParser, KickCParser.FileContext fileCtx, Program program) { this.cParser = cParser; @@ -57,7 +55,6 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor(); this.defaultMemoryArea = Variable.MemoryArea.ZEROPAGE_MEMORY; - this.directiveContext = new VariableBuilderContext(); scopeStack.push(program.getScope()); } @@ -266,11 +263,12 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor directives = declVarDirectives; - Variable param = Variable.createPhiMaster(ctx.NAME().getText(), type, getCurrentScope(), defaultMemoryArea, currentDataSegment); - // Add directives - directiveContext.applyDirectives(param, true, false, directives, new StatementSource(ctx)); + String varName = ctx.NAME().getText(); + VariableBuilder varBuilder = new VariableBuilder(varName, getCurrentScope(), true, declVarType, null, declVarDirectives, currentDataSegment); + // TODO: const parameter pointer should be no-modify! + if(varBuilder.hasDirective(Directive.Const.class)) + throw new CompileError("Error! Const parameters not supported " + varName + " in " + getCurrentScope().getFullName() + "()"); + Variable param = varBuilder.build(); exitDeclTypes(); return param; } @@ -578,56 +576,18 @@ public class Pass0GenerateStatementSequence extends KickCParserBaseVisitor varDirectives = declVarDirectives; String varName = ctx.NAME().getText(); Variable lValue; if(varType != null) { - try { - lValue = getCurrentScope().add(Variable.createPhiMaster(varName, varType, getCurrentScope(), defaultMemoryArea, currentDataSegment)); - } catch(CompileError e) { - throw new CompileError(e.getMessage(), statementSource); - } - // Add directives - directiveContext.applyDirectives(lValue, false, false, varDirectives, statementSource); + VariableBuilder varBuilder = new VariableBuilder(varName, blockScope, false, varType, null, declVarDirectives, currentDataSegment); + lValue = varBuilder.build(); } else { lValue = getCurrentScope().getVariable(varName); if(lValue == null) {