mirror of https://github.com/aamine/cbc
* convert all source codes to Java 5 using generics and foreach stmt.
git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4067 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
parent
9003c4fd72
commit
cd37fb1f02
|
@ -1,3 +1,8 @@
|
|||
Mon Sep 29 03:46:51 2008 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* convert all source codes to Java 5 using generics and foreach
|
||||
stmt.
|
||||
|
||||
Sun Sep 28 07:19:43 2008 Minero Aoki <aamine@loveruby.net>
|
||||
|
||||
* net/loveruby/cflat/compiler/Options.java (getOutputFileName):
|
||||
|
|
|
@ -13,7 +13,8 @@
|
|||
<mkdir dir="${build.dir}" />
|
||||
<mkdir dir="${build.classes.dir}" />
|
||||
<javac destdir="${build.classes.dir}" srcdir="${src.dir}"
|
||||
debug="true" source="1.4">
|
||||
debug="true" optimize="true">
|
||||
<compilerarg value="-Xlint:unchecked" />
|
||||
<include name="net/**/*.java" />
|
||||
</javac>
|
||||
<jar jarfile="${build.jar}" basedir="${build.classes.dir}" />
|
||||
|
|
|
@ -2,5 +2,5 @@ package net.loveruby.cflat.asm;
|
|||
import java.util.List;
|
||||
|
||||
public interface AsmOptimizer {
|
||||
public List optimize(List assemblies);
|
||||
public List<Assembly> optimize(List<Assembly> assemblies);
|
||||
}
|
||||
|
|
|
@ -2,24 +2,22 @@ package net.loveruby.cflat.asm;
|
|||
import java.util.*;
|
||||
|
||||
public class AsmStatistics {
|
||||
protected Map registerUsage; // Map<Register, Integer>
|
||||
protected Map insnUsage; // Map<String, Integer>
|
||||
protected Map labelUsage; // Map<Label, Integer>
|
||||
protected Map<Register, Integer> registerUsage;
|
||||
protected Map<String, Integer> insnUsage;
|
||||
protected Map<Label, Integer> labelUsage;
|
||||
|
||||
static public AsmStatistics collect(List assemblies) {
|
||||
static public AsmStatistics collect(List<Assembly> assemblies) {
|
||||
AsmStatistics stats = new AsmStatistics();
|
||||
Iterator asms = assemblies.iterator();
|
||||
while (asms.hasNext()) {
|
||||
Assembly asm = (Assembly)asms.next();
|
||||
for (Assembly asm : assemblies) {
|
||||
asm.collectStatistics(stats);
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
|
||||
public AsmStatistics() {
|
||||
registerUsage = new HashMap();
|
||||
insnUsage = new HashMap();
|
||||
labelUsage = new HashMap();
|
||||
registerUsage = new HashMap<Register, Integer>();
|
||||
insnUsage = new HashMap<String, Integer>();
|
||||
labelUsage = new HashMap<Label, Integer>();
|
||||
}
|
||||
|
||||
public boolean doesRegisterUsed(Register reg) {
|
||||
|
@ -54,17 +52,17 @@ public class AsmStatistics {
|
|||
incrementCount(labelUsage, label);
|
||||
}
|
||||
|
||||
protected int fetchCount(Map m, Object key) {
|
||||
Integer n = (Integer)m.get(key);
|
||||
protected <K> int fetchCount(Map<K, Integer> m, K key) {
|
||||
Integer n = m.get(key);
|
||||
if (n == null) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
return n.intValue();
|
||||
return n;
|
||||
}
|
||||
}
|
||||
|
||||
protected void incrementCount(Map m, Object key) {
|
||||
m.put(key, new Integer(fetchCount(m, key) + 1));
|
||||
protected <K> void incrementCount(Map<K, Integer> m, K key) {
|
||||
m.put(key, fetchCount(m, key) + 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ import net.loveruby.cflat.utils.*;
|
|||
import java.util.*;
|
||||
|
||||
public class Assembler {
|
||||
protected List assemblies; // List<Assembly>
|
||||
protected List<Assembly> assemblies;
|
||||
protected Type naturalType;
|
||||
protected int commentIndentLevel;
|
||||
|
||||
|
@ -13,24 +13,22 @@ public class Assembler {
|
|||
}
|
||||
|
||||
public Assembler(Type naturalType) {
|
||||
this.assemblies = new ArrayList();
|
||||
this.assemblies = new ArrayList<Assembly>();
|
||||
this.naturalType = naturalType;
|
||||
this.commentIndentLevel = 0;
|
||||
}
|
||||
|
||||
public List assemblies() {
|
||||
public List<Assembly> assemblies() {
|
||||
return this.assemblies;
|
||||
}
|
||||
|
||||
public void addAll(List assemblies) {
|
||||
public void addAll(List<Assembly> assemblies) {
|
||||
this.assemblies.addAll(assemblies);
|
||||
}
|
||||
|
||||
public String toSource() {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Iterator asms = assemblies.iterator();
|
||||
while (asms.hasNext()) {
|
||||
Assembly asm = (Assembly)asms.next();
|
||||
for (Assembly asm : assemblies) {
|
||||
buf.append(asm.toSource());
|
||||
buf.append("\n");
|
||||
}
|
||||
|
|
|
@ -8,9 +8,12 @@ public class IntegerLiteral extends Literal {
|
|||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof IntegerLiteral)) return false;
|
||||
IntegerLiteral lit = (IntegerLiteral)other;
|
||||
return lit.value == this.value;
|
||||
return (other instanceof IntegerLiteral)
|
||||
&& equals((IntegerLiteral)other);
|
||||
}
|
||||
|
||||
public boolean equals(IntegerLiteral other) {
|
||||
return other.value == this.value;
|
||||
}
|
||||
|
||||
public long value() {
|
||||
|
|
|
@ -3,19 +3,19 @@ import net.loveruby.cflat.utils.Cursor;
|
|||
import java.util.*;
|
||||
|
||||
public class PeepholeOptimizer implements AsmOptimizer {
|
||||
protected Map filterSet; // Map<String, List<Filter>>
|
||||
protected Map<String, List<Filter>> filterSet;
|
||||
|
||||
public PeepholeOptimizer() {
|
||||
this.filterSet = new HashMap();
|
||||
this.filterSet = new HashMap<String, List<Filter>>();
|
||||
}
|
||||
|
||||
public void add(Filter filter) {
|
||||
String[] heads = filter.patternHeads();
|
||||
for (int i = 0; i < heads.length; i++) {
|
||||
String head = heads[i];
|
||||
List list = (List)filterSet.get(head);
|
||||
List<Filter> list = filterSet.get(head);
|
||||
if (list == null) {
|
||||
list = new ArrayList();
|
||||
list = new ArrayList<Filter>();
|
||||
list.add(filter);
|
||||
filterSet.put(head, list);
|
||||
}
|
||||
|
@ -25,11 +25,11 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
|||
}
|
||||
}
|
||||
|
||||
public List optimize(List assemblies) {
|
||||
List result = new ArrayList();
|
||||
Cursor cursor = new Cursor(assemblies);
|
||||
public List<Assembly> optimize(List<Assembly> assemblies) {
|
||||
List<Assembly> result = new ArrayList<Assembly>();
|
||||
Cursor<Assembly> cursor = new Cursor<Assembly>(assemblies);
|
||||
while (cursor.hasNext()) {
|
||||
Assembly asm = (Assembly)cursor.next();
|
||||
Assembly asm = cursor.next();
|
||||
if (asm.isInstruction()) {
|
||||
Filter matched = matchFilter(cursor);
|
||||
if (matched != null) {
|
||||
|
@ -42,14 +42,12 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
|||
return result;
|
||||
}
|
||||
|
||||
protected Filter matchFilter(Cursor asms) {
|
||||
protected Filter matchFilter(Cursor<Assembly> asms) {
|
||||
Instruction insn = (Instruction)asms.current();
|
||||
List filters = (List)filterSet.get(insn.mnemonic());
|
||||
List<Filter> filters = filterSet.get(insn.mnemonic());
|
||||
if (filters == null) return null;
|
||||
if (filters.isEmpty()) return null;
|
||||
Iterator it = filters.iterator();
|
||||
while (it.hasNext()) {
|
||||
Filter filter = (Filter)it.next();
|
||||
for (Filter filter : filters) {
|
||||
if (filter.match(asms)) {
|
||||
return filter;
|
||||
}
|
||||
|
@ -180,8 +178,8 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
|||
|
||||
abstract class Filter {
|
||||
abstract public String[] patternHeads();
|
||||
abstract public boolean match(Cursor asms);
|
||||
abstract public void optimize(Cursor src, List dest);
|
||||
abstract public boolean match(Cursor<Assembly> asms);
|
||||
abstract public void optimize(Cursor<Assembly> src, List<Assembly> dest);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -202,11 +200,11 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
|||
return new String[] { pattern.name };
|
||||
}
|
||||
|
||||
public boolean match(Cursor asms) {
|
||||
public boolean match(Cursor<Assembly> asms) {
|
||||
return pattern.match((Instruction)asms.current());
|
||||
}
|
||||
|
||||
public void optimize(Cursor src, List dest) {
|
||||
public void optimize(Cursor<Assembly> src, List<Assembly> dest) {
|
||||
if (transform == null) {
|
||||
; // remove instruction
|
||||
}
|
||||
|
@ -260,13 +258,13 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
|||
return jmpInsns();
|
||||
}
|
||||
|
||||
public void optimize(Cursor src, List dest) {
|
||||
public void optimize(Cursor<Assembly> src, List<Assembly> dest) {
|
||||
; // remove jump
|
||||
}
|
||||
|
||||
public boolean match(Cursor asms) {
|
||||
public boolean match(Cursor<Assembly> asms) {
|
||||
Instruction insn = (Instruction)asms.current();
|
||||
return doesLabelFollows(asms.dup(), insn.jmpDestination());
|
||||
return doesLabelFollows(asms.clone(), insn.jmpDestination());
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -281,9 +279,9 @@ public class PeepholeOptimizer implements AsmOptimizer {
|
|||
* mov
|
||||
* add
|
||||
*/
|
||||
protected boolean doesLabelFollows(Cursor asms, Label jmpDest) {
|
||||
protected boolean doesLabelFollows(Cursor<Assembly> asms, Label jmpDest) {
|
||||
while (asms.hasNext()) {
|
||||
Assembly asm = (Assembly)asms.next();
|
||||
Assembly asm = asms.next();
|
||||
if (asm.isLabel()) {
|
||||
Label label = (Label)asm;
|
||||
if (label.equals(jmpDest)) {
|
||||
|
|
|
@ -22,8 +22,8 @@ public class AST extends Node {
|
|||
return source.sourceName();
|
||||
}
|
||||
|
||||
public Iterator sourceTokens() {
|
||||
return source.token().iterator();
|
||||
public CflatToken sourceTokens() {
|
||||
return source.token();
|
||||
}
|
||||
|
||||
public void setTypeTable(TypeTable table) {
|
||||
|
@ -37,61 +37,64 @@ public class AST extends Node {
|
|||
return this.typeTable;
|
||||
}
|
||||
|
||||
public Iterator types() {
|
||||
List result = new ArrayList();
|
||||
public List<TypeDefinition> types() {
|
||||
List<TypeDefinition> result = new ArrayList<TypeDefinition>();
|
||||
result.addAll(declarations.defstructs());
|
||||
result.addAll(declarations.defunions());
|
||||
result.addAll(declarations.typedefs());
|
||||
return result.iterator();
|
||||
return result;
|
||||
}
|
||||
|
||||
public Iterator declarations() {
|
||||
List result = new ArrayList();
|
||||
public List<Entity> declarations() {
|
||||
List<Entity> result = new ArrayList<Entity>();
|
||||
result.addAll(declarations.funcdecls());
|
||||
result.addAll(declarations.vardecls());
|
||||
return result.iterator();
|
||||
return result;
|
||||
}
|
||||
|
||||
public Iterator entities() {
|
||||
List result = new ArrayList();
|
||||
public List<Entity> entities() {
|
||||
List<Entity> result = new ArrayList<Entity>();
|
||||
result.addAll(declarations.defvars());
|
||||
result.addAll(declarations.defuns());
|
||||
return result.iterator();
|
||||
return result;
|
||||
}
|
||||
|
||||
public Iterator variables() {
|
||||
return declarations.defvars().iterator();
|
||||
public List<DefinedVariable> definedVariables() {
|
||||
return declarations.defvars();
|
||||
}
|
||||
|
||||
public boolean functionDefined() {
|
||||
return !declarations.defuns().isEmpty();
|
||||
}
|
||||
|
||||
public Iterator functions() {
|
||||
return declarations.defuns().iterator();
|
||||
public List<DefinedFunction> definedFunctions() {
|
||||
return declarations.defuns();
|
||||
}
|
||||
|
||||
public Iterator allFunctions() {
|
||||
List result = new ArrayList();
|
||||
public List<Function> allFunctions() {
|
||||
List<Function> result = new ArrayList<Function>();
|
||||
result.addAll(declarations.defuns());
|
||||
result.addAll(declarations.funcdecls());
|
||||
return result.iterator();
|
||||
return result;
|
||||
}
|
||||
|
||||
public ToplevelScope scope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
public Iterator allGlobalVariables() {
|
||||
return scope.allGlobalVariables().iterator();
|
||||
/** a list of all defined/declared global-scope variables */
|
||||
public List<Variable> allGlobalVariables() {
|
||||
return scope.allGlobalVariables();
|
||||
}
|
||||
|
||||
public Iterator globalVariables() {
|
||||
return scope.globalVariables().iterator();
|
||||
/** a list of defined initialized global variables */
|
||||
public List<DefinedVariable> definedGlobalVariables() {
|
||||
return scope.definedGlobalVariables();
|
||||
}
|
||||
|
||||
public Iterator commonSymbols() {
|
||||
return scope.commonSymbols().iterator();
|
||||
/** a list of defined uninitialized global variables */
|
||||
public List<DefinedVariable> definedCommonSymbols() {
|
||||
return scope.definedCommonSymbols();
|
||||
}
|
||||
|
||||
public ConstantTable constantTable() {
|
||||
|
@ -103,8 +106,8 @@ public class AST extends Node {
|
|||
}
|
||||
|
||||
protected void _dump(Dumper d) {
|
||||
d.printNodeList("variables", variables());
|
||||
d.printNodeList("functions", functions());
|
||||
d.printNodeList("variables", definedVariables());
|
||||
d.printNodeList("functions", definedFunctions());
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
|
|
|
@ -2,27 +2,27 @@ package net.loveruby.cflat.ast;
|
|||
import java.util.*;
|
||||
|
||||
public class BlockNode extends StmtNode {
|
||||
protected List variables;
|
||||
protected List stmts;
|
||||
protected List<DefinedVariable> variables;
|
||||
protected List<Node> stmts;
|
||||
protected LocalScope scope;
|
||||
|
||||
public BlockNode(Location loc, List vars, List ss) {
|
||||
public BlockNode(Location loc, List<DefinedVariable> vars, List<Node> stmts) {
|
||||
super(loc);
|
||||
variables = vars;
|
||||
stmts = ss;
|
||||
this.variables = vars;
|
||||
this.stmts = stmts;
|
||||
}
|
||||
|
||||
public Iterator variables() {
|
||||
return variables.iterator();
|
||||
public List<DefinedVariable> variables() {
|
||||
return variables;
|
||||
}
|
||||
|
||||
public Iterator stmts() {
|
||||
return stmts.iterator();
|
||||
public List<Node> stmts() {
|
||||
return stmts;
|
||||
}
|
||||
|
||||
public Node tailStmt() {
|
||||
if (stmts.isEmpty()) return null;
|
||||
return (Node)stmts.get(stmts.size() - 1);
|
||||
return stmts.get(stmts.size() - 1);
|
||||
}
|
||||
|
||||
public LocalScope scope() {
|
||||
|
|
|
@ -5,10 +5,11 @@ import java.util.*;
|
|||
public class CaseNode extends StmtNode {
|
||||
protected LabelPool pool;
|
||||
protected Label beginLabel;
|
||||
protected List values; // List<Node>
|
||||
protected List<ExprNode> values;
|
||||
protected BlockNode body;
|
||||
|
||||
public CaseNode(Location loc, LabelPool pool, List values, BlockNode body) {
|
||||
public CaseNode(Location loc, LabelPool pool,
|
||||
List<ExprNode> values, BlockNode body) {
|
||||
super(loc);
|
||||
this.pool = pool;
|
||||
this.values = values;
|
||||
|
@ -16,8 +17,8 @@ public class CaseNode extends StmtNode {
|
|||
this.beginLabel = null;
|
||||
}
|
||||
|
||||
public Iterator values() {
|
||||
return values.iterator();
|
||||
public List<ExprNode> values() {
|
||||
return values;
|
||||
}
|
||||
|
||||
public boolean isDefault() {
|
||||
|
|
|
@ -7,7 +7,7 @@ import java.util.*;
|
|||
/**
|
||||
* Token wrapper.
|
||||
*/
|
||||
public class CflatToken {
|
||||
public class CflatToken implements Iterable<CflatToken> {
|
||||
protected Token token;
|
||||
protected boolean isSpecial;
|
||||
|
||||
|
@ -52,28 +52,28 @@ public class CflatToken {
|
|||
return TextUtils.dumpString(token.image);
|
||||
}
|
||||
|
||||
public Iterator iterator() {
|
||||
return buildTokenList(new ArrayList(), token, false).iterator();
|
||||
public Iterator<CflatToken> iterator() {
|
||||
return buildTokenList(token, false).iterator();
|
||||
}
|
||||
|
||||
protected Iterator tokensWithoutFirstSpecials() {
|
||||
return buildTokenList(new ArrayList(), token, true).iterator();
|
||||
protected List<CflatToken> tokensWithoutFirstSpecials() {
|
||||
return buildTokenList(token, true);
|
||||
}
|
||||
|
||||
protected List buildTokenList(List tokens, Token first,
|
||||
boolean rejectFirstSpecials) {
|
||||
protected List<CflatToken> buildTokenList(Token first, boolean rejectFirstSpecials) {
|
||||
List<CflatToken> result = new ArrayList<CflatToken>();
|
||||
boolean rejectSpecials = rejectFirstSpecials;
|
||||
for (Token t = first; t != null; t = t.next) {
|
||||
if (t.specialToken != null && !rejectSpecials) {
|
||||
Token s = specialTokenHead(t.specialToken);
|
||||
for (; s != null; s = s.next) {
|
||||
tokens.add(new CflatToken(s));
|
||||
result.add(new CflatToken(s));
|
||||
}
|
||||
}
|
||||
tokens.add(new CflatToken(t));
|
||||
result.add(new CflatToken(t));
|
||||
rejectSpecials = false;
|
||||
}
|
||||
return tokens;
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Token specialTokenHead(Token firstSpecial) {
|
||||
|
@ -86,9 +86,7 @@ public class CflatToken {
|
|||
|
||||
public String includedLine() {
|
||||
StringBuffer buf = new StringBuffer();
|
||||
Iterator toks = tokensWithoutFirstSpecials();
|
||||
while (toks.hasNext()) {
|
||||
CflatToken t = (CflatToken)toks.next();
|
||||
for (CflatToken t : tokensWithoutFirstSpecials()) {
|
||||
int idx = t.image().indexOf("\n");
|
||||
if (idx >= 0) {
|
||||
buf.append(t.image().substring(0, idx));
|
||||
|
|
|
@ -3,10 +3,10 @@ import net.loveruby.cflat.type.*;
|
|||
import java.util.*;
|
||||
|
||||
abstract public class CompositeTypeDefinition extends TypeDefinition {
|
||||
protected List members; // List<Slot>
|
||||
protected List<Slot> members;
|
||||
|
||||
public CompositeTypeDefinition(Location loc,
|
||||
TypeRef ref, String name, List membs) {
|
||||
public CompositeTypeDefinition(Location loc, TypeRef ref,
|
||||
String name, List<Slot> membs) {
|
||||
super(loc, ref, name);
|
||||
members = membs;
|
||||
}
|
||||
|
@ -17,7 +17,7 @@ abstract public class CompositeTypeDefinition extends TypeDefinition {
|
|||
|
||||
abstract public String kind();
|
||||
|
||||
public List members() {
|
||||
public List<Slot> members() {
|
||||
return members;
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import java.util.*;
|
||||
|
||||
public class ConstantTable {
|
||||
protected Map table;
|
||||
public class ConstantTable implements Iterable<ConstantEntry> {
|
||||
protected Map<String, ConstantEntry> table;
|
||||
protected long id;
|
||||
|
||||
public ConstantTable() {
|
||||
table = new LinkedHashMap();
|
||||
table = new LinkedHashMap<String, ConstantEntry>();
|
||||
id = 0;
|
||||
}
|
||||
|
||||
|
@ -15,7 +15,7 @@ public class ConstantTable {
|
|||
}
|
||||
|
||||
public ConstantEntry intern(String s) {
|
||||
ConstantEntry ent = (ConstantEntry)table.get(s);
|
||||
ConstantEntry ent = table.get(s);
|
||||
if (ent == null) {
|
||||
ent = new ConstantEntry(id++, s);
|
||||
table.put(s, ent);
|
||||
|
@ -23,7 +23,11 @@ public class ConstantTable {
|
|||
return ent;
|
||||
}
|
||||
|
||||
public Iterator entries() {
|
||||
public Collection<ConstantEntry> entries() {
|
||||
return table.values();
|
||||
}
|
||||
|
||||
public Iterator<ConstantEntry> iterator() {
|
||||
return table.values().iterator();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,91 +2,89 @@ package net.loveruby.cflat.ast;
|
|||
import java.util.*;
|
||||
|
||||
public class Declarations {
|
||||
protected Set defvars, vardecls, defuns, funcdecls;
|
||||
protected Set defstructs, defunions, typedefs;
|
||||
protected Set<DefinedVariable> defvars;
|
||||
protected Set<UndefinedVariable> vardecls;
|
||||
protected Set<DefinedFunction> defuns;
|
||||
protected Set<UndefinedFunction> funcdecls;
|
||||
protected Set<StructNode> defstructs;
|
||||
protected Set<UnionNode> defunions;
|
||||
protected Set<TypedefNode> typedefs;
|
||||
|
||||
public Declarations() {
|
||||
defvars = new LinkedHashSet();
|
||||
vardecls = new LinkedHashSet();
|
||||
defuns = new LinkedHashSet();
|
||||
funcdecls = new LinkedHashSet();
|
||||
defstructs = new LinkedHashSet();
|
||||
defunions = new LinkedHashSet();
|
||||
typedefs = new LinkedHashSet();
|
||||
defvars = new LinkedHashSet<DefinedVariable>();
|
||||
vardecls = new LinkedHashSet<UndefinedVariable>();
|
||||
defuns = new LinkedHashSet<DefinedFunction>();
|
||||
funcdecls = new LinkedHashSet<UndefinedFunction>();
|
||||
defstructs = new LinkedHashSet<StructNode>();
|
||||
defunions = new LinkedHashSet<UnionNode>();
|
||||
typedefs = new LinkedHashSet<TypedefNode>();
|
||||
}
|
||||
|
||||
public void add(Declarations decls) {
|
||||
updateSet(vardecls, decls.vardecls());
|
||||
updateSet(funcdecls, decls.funcdecls());
|
||||
updateSet(defstructs, decls.defstructs());
|
||||
updateSet(defunions, decls.defunions());
|
||||
updateSet(typedefs, decls.typedefs());
|
||||
}
|
||||
|
||||
protected void updateSet(Set s, List items) {
|
||||
Iterator i = items.iterator();
|
||||
while (i.hasNext()) {
|
||||
s.add(i.next());
|
||||
}
|
||||
vardecls.addAll(decls.vardecls());
|
||||
funcdecls.addAll(decls.funcdecls());
|
||||
defstructs.addAll(decls.defstructs());
|
||||
defunions.addAll(decls.defunions());
|
||||
typedefs.addAll(decls.typedefs());
|
||||
}
|
||||
|
||||
public void addDefvar(DefinedVariable var) {
|
||||
defvars.add(var);
|
||||
}
|
||||
|
||||
public void addDefvars(List vars) {
|
||||
updateSet(defvars, vars);
|
||||
public void addDefvars(List<DefinedVariable> vars) {
|
||||
defvars.addAll(vars);
|
||||
}
|
||||
|
||||
public List defvars() {
|
||||
return new ArrayList(defvars);
|
||||
public List<DefinedVariable> defvars() {
|
||||
return new ArrayList<DefinedVariable>(defvars);
|
||||
}
|
||||
|
||||
public void addVardecl(UndefinedVariable var) {
|
||||
vardecls.add(var);
|
||||
}
|
||||
|
||||
public List vardecls() {
|
||||
return new ArrayList(vardecls);
|
||||
public List<UndefinedVariable> vardecls() {
|
||||
return new ArrayList<UndefinedVariable>(vardecls);
|
||||
}
|
||||
|
||||
public void addDefun(Function func) {
|
||||
public void addDefun(DefinedFunction func) {
|
||||
defuns.add(func);
|
||||
}
|
||||
|
||||
public List defuns() {
|
||||
return new ArrayList(defuns);
|
||||
public List<DefinedFunction> defuns() {
|
||||
return new ArrayList<DefinedFunction>(defuns);
|
||||
}
|
||||
|
||||
public void addFuncdecl(UndefinedFunction func) {
|
||||
funcdecls.add(func);
|
||||
}
|
||||
|
||||
public List funcdecls() {
|
||||
return new ArrayList(funcdecls);
|
||||
public List<UndefinedFunction> funcdecls() {
|
||||
return new ArrayList<UndefinedFunction>(funcdecls);
|
||||
}
|
||||
|
||||
public void addDefstruct(StructNode n) {
|
||||
defstructs.add(n);
|
||||
}
|
||||
|
||||
public List defstructs() {
|
||||
return new ArrayList(defstructs);
|
||||
public List<StructNode> defstructs() {
|
||||
return new ArrayList<StructNode>(defstructs);
|
||||
}
|
||||
|
||||
public void addDefunion(UnionNode n) {
|
||||
defunions.add(n);
|
||||
}
|
||||
|
||||
public List defunions() {
|
||||
return new ArrayList(defunions);
|
||||
public List<UnionNode> defunions() {
|
||||
return new ArrayList<UnionNode>(defunions);
|
||||
}
|
||||
|
||||
public void addTypedef(TypedefNode n) {
|
||||
typedefs.add(n);
|
||||
}
|
||||
|
||||
public List typedefs() {
|
||||
return new ArrayList(typedefs);
|
||||
public List<TypedefNode> typedefs() {
|
||||
return new ArrayList<TypedefNode>(typedefs);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,24 +9,27 @@ public class DefinedFunction extends Function {
|
|||
protected LabelPool labelPool;
|
||||
protected Params params;
|
||||
protected BlockNode body;
|
||||
protected Map jumpMap;
|
||||
protected Map<String, JumpEntry> jumpMap;
|
||||
protected LocalScope scope;
|
||||
|
||||
public DefinedFunction(LabelPool pool, boolean priv, TypeNode type,
|
||||
String name, Params params, BlockNode body) {
|
||||
public DefinedFunction(LabelPool pool,
|
||||
boolean priv,
|
||||
TypeNode type,
|
||||
String name,
|
||||
Params params,
|
||||
BlockNode body) {
|
||||
super(priv, type, name);
|
||||
this.labelPool = pool;
|
||||
this.params = params;
|
||||
this.body = body;
|
||||
this.jumpMap = new HashMap();
|
||||
this.jumpMap = new HashMap<String, JumpEntry>();
|
||||
}
|
||||
|
||||
public boolean isDefined() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Returns an iterator to the list of parameter slots (Slot). */
|
||||
public Iterator parameters() {
|
||||
public List<Parameter> parameters() {
|
||||
return params.parameters();
|
||||
}
|
||||
|
||||
|
@ -43,7 +46,7 @@ public class DefinedFunction extends Function {
|
|||
* Does NOT include paramters.
|
||||
* Does NOT include static local variables.
|
||||
*/
|
||||
public Iterator localVariables() {
|
||||
public List<DefinedVariable> localVariables() {
|
||||
return scope.allLocalVariables();
|
||||
}
|
||||
|
||||
|
@ -79,7 +82,7 @@ public class DefinedFunction extends Function {
|
|||
}
|
||||
|
||||
protected JumpEntry getJumpEntry(String name) {
|
||||
JumpEntry ent = (JumpEntry)jumpMap.get(name);
|
||||
JumpEntry ent = jumpMap.get(name);
|
||||
if (ent == null) {
|
||||
ent = new JumpEntry(labelPool.newLabel());
|
||||
jumpMap.put(name, ent);
|
||||
|
@ -88,11 +91,9 @@ public class DefinedFunction extends Function {
|
|||
}
|
||||
|
||||
public void checkJumpLinks(ErrorHandler handler) {
|
||||
Iterator ents = jumpMap.entrySet().iterator();
|
||||
while (ents.hasNext()) {
|
||||
Map.Entry ent = (Map.Entry)ents.next();
|
||||
String labelName = (String)ent.getKey();
|
||||
JumpEntry jump = (JumpEntry)ent.getValue();
|
||||
for (Map.Entry<String, JumpEntry> ent : jumpMap.entrySet()) {
|
||||
String labelName = ent.getKey();
|
||||
JumpEntry jump = ent.getValue();
|
||||
if (!jump.isDefined) {
|
||||
handler.error(jump.location,
|
||||
name + ": undefined label: " + labelName);
|
||||
|
|
|
@ -15,24 +15,14 @@ public class Dumper {
|
|||
|
||||
public void printClass(Object obj, Location loc) {
|
||||
printIndent();
|
||||
stream.println("<<" + className(obj) + ">> (" + loc + ")");
|
||||
stream.println("<<" + obj.getClass().getSimpleName() + ">> (" + loc + ")");
|
||||
}
|
||||
|
||||
protected String className(Object obj) {
|
||||
String[] ids = obj.getClass().getName().split("\\.");
|
||||
return ids[ids.length - 1];
|
||||
}
|
||||
|
||||
public void printNodeList(String name, List list) {
|
||||
printNodeList(name, list.iterator());
|
||||
}
|
||||
|
||||
public void printNodeList(String name, Iterator list) {
|
||||
public void printNodeList(String name, List<? extends Node> nodes) {
|
||||
printIndent();
|
||||
stream.println(name + ":");
|
||||
indent();
|
||||
while (list.hasNext()) {
|
||||
Node n = (Node)list.next();
|
||||
for (Node n : nodes) {
|
||||
n.dump(this);
|
||||
}
|
||||
unindent();
|
||||
|
|
|
@ -1,97 +0,0 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import java.util.*;
|
||||
|
||||
public class FixedParams extends Params {
|
||||
protected Location location;
|
||||
protected List parameters;
|
||||
|
||||
public FixedParams(List params) {
|
||||
this(null, params);
|
||||
}
|
||||
|
||||
public FixedParams(Location loc, List params) {
|
||||
super();
|
||||
this.location = loc;
|
||||
this.parameters = params;
|
||||
}
|
||||
|
||||
public Location location() {
|
||||
return location;
|
||||
}
|
||||
|
||||
/**
|
||||
* For DefinedFunction and UndefinedFunction, returns an iterator to
|
||||
* the list of parameters (Parameter). For FunctionType, returns an
|
||||
* iterator to the list of parameter type (Type).
|
||||
*/
|
||||
public Iterator parameters() {
|
||||
return parameters.iterator();
|
||||
}
|
||||
|
||||
public int argc() {
|
||||
return parameters.size();
|
||||
}
|
||||
|
||||
public int minArgc() {
|
||||
return parameters.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* For DefinedFunction and UndefinedFunction, returns a list of
|
||||
* parameters (Parameter). For FunctionType, returns a list of
|
||||
* parameter types (Type).
|
||||
*/
|
||||
protected List parametersList() {
|
||||
return parameters;
|
||||
}
|
||||
|
||||
public boolean isVararg() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof FixedParams)) return false;
|
||||
FixedParams params = (FixedParams)other;
|
||||
return parameters.equals(params.parametersList());
|
||||
}
|
||||
|
||||
public Params internTypes(TypeTable table) {
|
||||
Iterator it = parameters.iterator();
|
||||
List types = new ArrayList();
|
||||
while (it.hasNext()) {
|
||||
types.add(table.get((TypeRef)it.next()));
|
||||
}
|
||||
return new FixedParams(location, types);
|
||||
}
|
||||
|
||||
public Params typeRefs() {
|
||||
Iterator it = parameters.iterator();
|
||||
List typerefs = new ArrayList();
|
||||
while (it.hasNext()) {
|
||||
Parameter param = (Parameter)it.next();
|
||||
typerefs.add(param.typeNode().typeRef());
|
||||
}
|
||||
return new FixedParams(location, typerefs);
|
||||
}
|
||||
|
||||
/** parameters is a list of Type when
|
||||
* this object is hold in FunctionType. */
|
||||
public Iterator types() {
|
||||
return parameters.iterator();
|
||||
}
|
||||
|
||||
public boolean isSameType(Params other) {
|
||||
if (other.isVararg()) return false;
|
||||
if (other.argc() != argc()) return false;
|
||||
Iterator types = types();
|
||||
Iterator otherTypes = other.types();
|
||||
while (types.hasNext()) {
|
||||
Type t = (Type)types.next();
|
||||
Type tt = (Type)otherTypes.next();
|
||||
if (t.isSameType(t))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
|
@ -5,9 +5,9 @@ import java.util.*;
|
|||
|
||||
public class FuncallNode extends ExprNode {
|
||||
protected ExprNode expr;
|
||||
protected List arguments;
|
||||
protected List<ExprNode> arguments;
|
||||
|
||||
public FuncallNode(ExprNode expr, List arguments) {
|
||||
public FuncallNode(ExprNode expr, List<ExprNode> arguments) {
|
||||
this.expr = expr;
|
||||
this.arguments = arguments;
|
||||
}
|
||||
|
@ -55,16 +55,16 @@ public class FuncallNode extends ExprNode {
|
|||
return arguments.size();
|
||||
}
|
||||
|
||||
public Iterator arguments() {
|
||||
return arguments.iterator();
|
||||
public List<ExprNode> arguments() {
|
||||
return arguments;
|
||||
}
|
||||
|
||||
// called from TypeChecker
|
||||
public void replaceArgs(List args) {
|
||||
public void replaceArgs(List<ExprNode> args) {
|
||||
this.arguments = args;
|
||||
}
|
||||
|
||||
public ListIterator finalArg() {
|
||||
public ListIterator<ExprNode> finalArg() {
|
||||
return arguments.listIterator(arguments.size());
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ abstract public class Function extends Entity {
|
|||
public boolean isFunction() { return true; }
|
||||
public boolean isInitialized() { return true; }
|
||||
abstract public boolean isDefined();
|
||||
abstract public Iterator parameters();
|
||||
abstract public List<Parameter> parameters();
|
||||
|
||||
public FunctionType functionType() {
|
||||
return type().getPointerType().baseType().getFunctionType();
|
||||
|
|
|
@ -4,83 +4,82 @@ import net.loveruby.cflat.exception.*;
|
|||
import java.util.*;
|
||||
|
||||
public class LocalScope extends Scope {
|
||||
protected long numAllEntities;
|
||||
protected Scope parent;
|
||||
protected Map<String, DefinedVariable> variables;
|
||||
|
||||
public LocalScope(Scope up) {
|
||||
super(up);
|
||||
numAllEntities = -1;
|
||||
public LocalScope(Scope parent) {
|
||||
super();
|
||||
this.parent = parent;
|
||||
parent.addChild(this);
|
||||
variables = new LinkedHashMap<String, DefinedVariable>();
|
||||
}
|
||||
|
||||
public boolean isToplevel() {
|
||||
return false;
|
||||
}
|
||||
|
||||
public Iterator children() {
|
||||
return children.iterator();
|
||||
public ToplevelScope toplevel() {
|
||||
return parent.toplevel();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns local variables defined in this scope.
|
||||
* Does NOT includes children's local variables.
|
||||
* Does NOT include static local variables.
|
||||
*/
|
||||
public Iterator variables() {
|
||||
return lvarList().iterator();
|
||||
public Scope parent() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns local variables defined in this scope.
|
||||
* Does NOT includes children's local variables.
|
||||
* Does NOT include static local variables.
|
||||
*/
|
||||
protected List lvarList() {
|
||||
List result = new ArrayList();
|
||||
Iterator ents = entities.values().iterator();
|
||||
while (ents.hasNext()) {
|
||||
Entity ent = (Entity)ents.next();
|
||||
if (ent instanceof DefinedVariable) {
|
||||
DefinedVariable var = (DefinedVariable)ent;
|
||||
if (!var.isPrivate()) {
|
||||
result.add(var);
|
||||
}
|
||||
}
|
||||
public List<LocalScope> children() {
|
||||
return children;
|
||||
}
|
||||
|
||||
public boolean isDefinedLocally(String name) {
|
||||
return variables.containsKey(name);
|
||||
}
|
||||
|
||||
/** Define variable in this scope. */
|
||||
// #@@range/defineVariable{
|
||||
public void defineVariable(DefinedVariable var) {
|
||||
if (variables.containsKey(var.name())) {
|
||||
throw new Error("duplicated variable: " + var.name());
|
||||
}
|
||||
return result;
|
||||
variables.put(var.name(), var);
|
||||
}
|
||||
// #@@}
|
||||
|
||||
/**
|
||||
* Returns the number of all entities in this scope.
|
||||
* Result includes the number of children's entities.
|
||||
*/
|
||||
public long numAllEntities() {
|
||||
if (numAllEntities < 0) {
|
||||
Iterator cs = allScopes().iterator();
|
||||
long n = 0;
|
||||
while (cs.hasNext()) {
|
||||
Scope c = (Scope)cs.next();
|
||||
n += c.numEntities();
|
||||
}
|
||||
numAllEntities = n;
|
||||
// #@@range/get{
|
||||
public Entity get(String name) throws SemanticException {
|
||||
DefinedVariable var = variables.get(name);
|
||||
if (var != null) {
|
||||
return var;
|
||||
}
|
||||
else {
|
||||
return parent.get(name);
|
||||
}
|
||||
return numAllEntities;
|
||||
}
|
||||
// #@@}
|
||||
|
||||
/**
|
||||
* Returns all local variables in this scope.
|
||||
* The result DOES includes all nested local variables,
|
||||
* while it does NOT include static local variables.
|
||||
*/
|
||||
public Iterator allLocalVariables() {
|
||||
return allLocalVariablesList().iterator();
|
||||
public List<DefinedVariable> allLocalVariables() {
|
||||
List<DefinedVariable> result = new ArrayList<DefinedVariable>();
|
||||
for (LocalScope s : allLocalScopes()) {
|
||||
result.addAll(s.localVariables());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// List<DefinedVariable>
|
||||
protected List allLocalVariablesList() {
|
||||
List result = new ArrayList();
|
||||
Iterator scopes = allScopes().iterator();
|
||||
while (scopes.hasNext()) {
|
||||
LocalScope s = (LocalScope)scopes.next();
|
||||
result.addAll(s.lvarList());
|
||||
/**
|
||||
* Returns local variables defined in this scope.
|
||||
* Does NOT includes children's local variables.
|
||||
* Does NOT include static local variables.
|
||||
*/
|
||||
public List<DefinedVariable> localVariables() {
|
||||
List<DefinedVariable> result = new ArrayList<DefinedVariable>();
|
||||
for (DefinedVariable var : variables.values()) {
|
||||
if (!var.isPrivate()) {
|
||||
result.add(var);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -88,14 +87,10 @@ public class LocalScope extends Scope {
|
|||
/**
|
||||
* Returns all static local variables defined in this scope.
|
||||
*/
|
||||
public List staticLocalVariables() {
|
||||
List result = new ArrayList();
|
||||
Iterator scopes = allScopes().iterator();
|
||||
while (scopes.hasNext()) {
|
||||
LocalScope s = (LocalScope)scopes.next();
|
||||
Iterator vars = s.entities.values().iterator();
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
public List<DefinedVariable> staticLocalVariables() {
|
||||
List<DefinedVariable> result = new ArrayList<DefinedVariable>();
|
||||
for (LocalScope s : allLocalScopes()) {
|
||||
for (DefinedVariable var : s.variables.values()) {
|
||||
if (var.isPrivate()) {
|
||||
result.add(var);
|
||||
}
|
||||
|
@ -103,4 +98,29 @@ public class LocalScope extends Scope {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Returns a list of all child scopes including this scope.
|
||||
protected List<LocalScope> allLocalScopes() {
|
||||
List<LocalScope> result = new ArrayList<LocalScope>();
|
||||
collectScope(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void collectScope(List<LocalScope> buf) {
|
||||
buf.add(this);
|
||||
for (LocalScope s : children) {
|
||||
s.collectScope(buf);
|
||||
}
|
||||
}
|
||||
|
||||
public void checkReferences(ErrorHandler h) {
|
||||
for (DefinedVariable var : variables.values()) {
|
||||
if (!var.isRefered()) {
|
||||
h.warn(var.location(), "unused variable: " + var.name());
|
||||
}
|
||||
}
|
||||
for (LocalScope c : children) {
|
||||
c.checkReferences(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,55 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import java.util.*;
|
||||
|
||||
abstract public class ParamSlots<T> extends Node {
|
||||
protected Location location;
|
||||
protected List<T> paramDescriptors;
|
||||
protected boolean vararg;
|
||||
|
||||
public ParamSlots(List<T> paramDescs) {
|
||||
this(null, paramDescs);
|
||||
}
|
||||
|
||||
public ParamSlots(Location loc, List<T> paramDescs) {
|
||||
this(loc, paramDescs, false);
|
||||
}
|
||||
|
||||
protected ParamSlots(Location loc, List<T> paramDescs, boolean vararg) {
|
||||
super();
|
||||
this.location = loc;
|
||||
this.paramDescriptors = paramDescs;
|
||||
this.vararg = vararg;
|
||||
}
|
||||
|
||||
public int argc() {
|
||||
if (vararg) {
|
||||
throw new Error("must not happen: Param#argc for vararg");
|
||||
}
|
||||
return paramDescriptors.size();
|
||||
}
|
||||
|
||||
public int minArgc() {
|
||||
return paramDescriptors.size();
|
||||
}
|
||||
|
||||
public void acceptVarargs() {
|
||||
this.vararg = true;
|
||||
}
|
||||
|
||||
public boolean isVararg() {
|
||||
return vararg;
|
||||
}
|
||||
|
||||
public Location location() {
|
||||
return location;
|
||||
}
|
||||
|
||||
protected void _dump(Dumper d) {
|
||||
throw new Error("must not happen: ParamSlots#_dump");
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
throw new Error("must not happen: ParamSlots#accept");
|
||||
}
|
||||
}
|
|
@ -1,27 +1,35 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.type.TypeRef;
|
||||
import net.loveruby.cflat.type.ParamTypeRefs;
|
||||
import java.util.*;
|
||||
|
||||
abstract public class Params extends Node {
|
||||
public Params() {
|
||||
super();
|
||||
public class Params extends ParamSlots<Parameter> {
|
||||
public Params(Location loc, List<Parameter> paramDescs) {
|
||||
super(loc, paramDescs, false);
|
||||
}
|
||||
|
||||
abstract public Iterator parameters();
|
||||
abstract public boolean isVararg();
|
||||
abstract public int argc();
|
||||
abstract public int minArgc();
|
||||
abstract public boolean equals(Object other);
|
||||
abstract public Params internTypes(TypeTable table);
|
||||
abstract public Params typeRefs();
|
||||
abstract public Iterator types();
|
||||
abstract public boolean isSameType(Params other);
|
||||
public List<Parameter> parameters() {
|
||||
return paramDescriptors;
|
||||
}
|
||||
|
||||
public ParamTypeRefs parametersTypeRef() {
|
||||
List<TypeRef> typerefs = new ArrayList<TypeRef>();
|
||||
for (Parameter param : paramDescriptors) {
|
||||
typerefs.add(param.typeNode().typeRef());
|
||||
}
|
||||
return new ParamTypeRefs(location, typerefs, vararg);
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
return (other instanceof Params) && equals((Params)other);
|
||||
}
|
||||
|
||||
public boolean equals(Params other) {
|
||||
return other.vararg == vararg
|
||||
&& other.paramDescriptors.equals(paramDescriptors);
|
||||
}
|
||||
|
||||
protected void _dump(Dumper d) {
|
||||
d.printNodeList("parameters", parameters());
|
||||
}
|
||||
|
||||
public void accept(ASTVisitor visitor) {
|
||||
throw new Error("do not use Params#accept");
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,97 +4,19 @@ import net.loveruby.cflat.exception.*;
|
|||
import java.util.*;
|
||||
|
||||
abstract public class Scope {
|
||||
protected Scope parent;
|
||||
protected List children;
|
||||
protected Map entities;
|
||||
protected long numAllEntities;
|
||||
protected List<LocalScope> children;
|
||||
|
||||
public Scope(Scope up) {
|
||||
parent = up;
|
||||
if (up != null) up.addChild(this);
|
||||
children = new ArrayList();
|
||||
numAllEntities = -1;
|
||||
entities = new LinkedHashMap();
|
||||
public Scope() {
|
||||
children = new ArrayList<LocalScope>();
|
||||
}
|
||||
|
||||
abstract public boolean isToplevel();
|
||||
abstract public ToplevelScope toplevel();
|
||||
abstract public Scope parent();
|
||||
|
||||
public ToplevelScope toplevel() {
|
||||
Scope s = this;
|
||||
while (!s.isToplevel()) {
|
||||
s = s.parent;
|
||||
}
|
||||
return (ToplevelScope)s;
|
||||
}
|
||||
|
||||
// Returns parent scope.
|
||||
// If this scope is a TopScope, parent() returns null.
|
||||
public Scope parent() {
|
||||
return parent;
|
||||
}
|
||||
|
||||
protected void addChild(Scope s) {
|
||||
protected void addChild(LocalScope s) {
|
||||
children.add(s);
|
||||
}
|
||||
|
||||
// Returns a list of all child scopes including this scope.
|
||||
protected List allScopes() {
|
||||
List result = new ArrayList();
|
||||
collectScope(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void collectScope(List buf) {
|
||||
buf.add(this);
|
||||
Iterator cs = children.iterator();
|
||||
while (cs.hasNext()) {
|
||||
Scope c = (Scope)cs.next();
|
||||
c.collectScope(buf);
|
||||
}
|
||||
}
|
||||
|
||||
/** Declare variable or function in this scope. */
|
||||
// #@@range/declareEntity{
|
||||
public void declareEntity(Entity ent) {
|
||||
if (entities.containsKey(ent.name())) {
|
||||
throw new Error("duplicated entity: " + ent.name());
|
||||
}
|
||||
entities.put(ent.name(), ent);
|
||||
}
|
||||
// #@@}
|
||||
|
||||
public boolean isDefinedLocally(String name) {
|
||||
return entities.containsKey(name);
|
||||
}
|
||||
|
||||
// #@@range/get{
|
||||
public Entity get(String name) throws SemanticException {
|
||||
Entity ent = (Entity)entities.get(name);
|
||||
if (ent != null) {
|
||||
return ent;
|
||||
}
|
||||
else {
|
||||
return parent.get(name);
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
||||
public long numEntities() {
|
||||
return entities.size();
|
||||
}
|
||||
|
||||
public void checkReferences(ErrorHandler h) {
|
||||
Iterator ents = entities.values().iterator();
|
||||
while (ents.hasNext()) {
|
||||
Entity ent = (Entity)ents.next();
|
||||
if (ent.isDefined() && ent.isPrivate() && !ent.isRefered()) {
|
||||
h.warn(ent.location(), "unused variable: " + ent.name());
|
||||
}
|
||||
}
|
||||
Iterator scopes = children.iterator();
|
||||
while (scopes.hasNext()) {
|
||||
Scope s = (Scope)scopes.next();
|
||||
s.checkReferences(h);
|
||||
}
|
||||
}
|
||||
abstract public Entity get(String name) throws SemanticException;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ import net.loveruby.cflat.type.*;
|
|||
import java.util.*;
|
||||
|
||||
public class StructNode extends CompositeTypeDefinition {
|
||||
public StructNode(Location loc, TypeRef ref, String name, List membs) {
|
||||
public StructNode(Location loc, TypeRef ref, String name, List<Slot> membs) {
|
||||
super(loc, ref, name, membs);
|
||||
}
|
||||
|
||||
|
|
|
@ -5,11 +5,11 @@ import java.util.*;
|
|||
public class SwitchNode extends StmtNode implements BreakableStmt {
|
||||
protected LabelPool pool;
|
||||
protected ExprNode cond;
|
||||
protected List cases;
|
||||
protected List<CaseNode> cases;
|
||||
protected Label endLabel;
|
||||
|
||||
public SwitchNode(Location loc, LabelPool pool,
|
||||
ExprNode cond, List cases) {
|
||||
ExprNode cond, List<CaseNode> cases) {
|
||||
super(loc);
|
||||
this.pool = pool;
|
||||
this.cond = cond;
|
||||
|
@ -20,8 +20,8 @@ public class SwitchNode extends StmtNode implements BreakableStmt {
|
|||
return cond;
|
||||
}
|
||||
|
||||
public Iterator cases() {
|
||||
return cases.iterator();
|
||||
public List<CaseNode> cases() {
|
||||
return cases;
|
||||
}
|
||||
|
||||
public Label endLabel() {
|
||||
|
|
|
@ -1,23 +1,45 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.compiler.ErrorHandler;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import net.loveruby.cflat.exception.*;
|
||||
import java.util.*;
|
||||
|
||||
public class ToplevelScope extends Scope {
|
||||
protected List staticLocalVariables;
|
||||
protected Map<String, Entity> entities;
|
||||
protected List<DefinedVariable> staticLocalVariables; // cache
|
||||
|
||||
public ToplevelScope() {
|
||||
super(null);
|
||||
super();
|
||||
entities = new LinkedHashMap<String, Entity>();
|
||||
staticLocalVariables = null;
|
||||
}
|
||||
|
||||
public boolean isToplevel() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public ToplevelScope toplevel() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public Scope parent() {
|
||||
return null;
|
||||
}
|
||||
|
||||
/** Declare variable or function in this scope. */
|
||||
// #@@range/declareEntity{
|
||||
public void declareEntity(Entity ent) {
|
||||
if (entities.containsKey(ent.name())) {
|
||||
throw new Error("duplicated entity: " + ent.name());
|
||||
}
|
||||
entities.put(ent.name(), ent);
|
||||
}
|
||||
// #@@}
|
||||
|
||||
/** Searches and gets entity searching scopes upto ToplevelScope. */
|
||||
// #@@range/get{
|
||||
public Entity get(String name) throws SemanticException {
|
||||
Entity ent = (Entity)entities.get(name);
|
||||
Entity ent = entities.get(name);
|
||||
if (ent == null) {
|
||||
throw new SemanticException("unresolved reference: " + name);
|
||||
}
|
||||
|
@ -25,32 +47,6 @@ public class ToplevelScope extends Scope {
|
|||
}
|
||||
// #@@}
|
||||
|
||||
protected List staticLocalVariables() {
|
||||
if (staticLocalVariables == null) {
|
||||
staticLocalVariables = new ArrayList();
|
||||
Iterator scopes = children.iterator();
|
||||
while (scopes.hasNext()) {
|
||||
LocalScope s = (LocalScope)scopes.next();
|
||||
staticLocalVariables.addAll(s.staticLocalVariables());
|
||||
}
|
||||
Map seqTable = new HashMap();
|
||||
Iterator vars = staticLocalVariables.iterator();
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
Long seq = (Long)seqTable.get(var.name());
|
||||
if (seq == null) {
|
||||
var.setSequence(0);
|
||||
seqTable.put(var.name(), new Long(1));
|
||||
}
|
||||
else {
|
||||
var.setSequence(seq.longValue());
|
||||
seqTable.put(var.name(), new Long(seq.longValue() + 1));
|
||||
}
|
||||
}
|
||||
}
|
||||
return staticLocalVariables;
|
||||
}
|
||||
|
||||
/** Returns a list of all global variables.
|
||||
* "All global variable" means:
|
||||
*
|
||||
|
@ -58,37 +54,25 @@ public class ToplevelScope extends Scope {
|
|||
* * defined or undefined
|
||||
* * public or private
|
||||
*/
|
||||
public List allGlobalVariables() {
|
||||
List result = new ArrayList();
|
||||
List src = new ArrayList();
|
||||
src.addAll(entities.values());
|
||||
src.addAll(staticLocalVariables());
|
||||
Iterator ents = src.iterator();
|
||||
while (ents.hasNext()) {
|
||||
Object ent = ents.next();
|
||||
public List<Variable> allGlobalVariables() {
|
||||
List<Variable> result = new ArrayList<Variable>();
|
||||
for (Entity ent : entities.values()) {
|
||||
if (ent instanceof Variable) {
|
||||
result.add(ent);
|
||||
result.add((Variable)ent);
|
||||
}
|
||||
}
|
||||
result.addAll(staticLocalVariables());
|
||||
return result;
|
||||
}
|
||||
|
||||
/** Returns the list of global variables.
|
||||
* A global variable is a variable which has
|
||||
* global scope and is initialized. */
|
||||
public List globalVariables() {
|
||||
List result = new ArrayList();
|
||||
List src = new ArrayList();
|
||||
src.addAll(entities.values());
|
||||
src.addAll(staticLocalVariables());
|
||||
Iterator ents = src.iterator();
|
||||
while (ents.hasNext()) {
|
||||
Object ent = ents.next();
|
||||
if (ent instanceof DefinedVariable) {
|
||||
DefinedVariable var = (DefinedVariable)ent;
|
||||
if (var.hasInitializer()) {
|
||||
result.add(var);
|
||||
}
|
||||
public List<DefinedVariable> definedGlobalVariables() {
|
||||
List<DefinedVariable> result = new ArrayList<DefinedVariable>();
|
||||
for (DefinedVariable var : definedGlobalScopeVariables()) {
|
||||
if (var.hasInitializer()) {
|
||||
result.add(var);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -97,21 +81,60 @@ public class ToplevelScope extends Scope {
|
|||
/** Returns the list of common symbols.
|
||||
* A common symbol is a variable which has
|
||||
* global scope and is not initialized. */
|
||||
public List commonSymbols() {
|
||||
List result = new ArrayList();
|
||||
List src = new ArrayList();
|
||||
src.addAll(entities.values());
|
||||
src.addAll(staticLocalVariables());
|
||||
Iterator ents = src.iterator();
|
||||
while (ents.hasNext()) {
|
||||
Object ent = ents.next();
|
||||
if (ent instanceof DefinedVariable) {
|
||||
DefinedVariable var = (DefinedVariable)ent;
|
||||
if (!var.hasInitializer()) {
|
||||
result.add(var);
|
||||
}
|
||||
public List<DefinedVariable> definedCommonSymbols() {
|
||||
List<DefinedVariable> result = new ArrayList<DefinedVariable>();
|
||||
for (DefinedVariable var : definedGlobalScopeVariables()) {
|
||||
if (!var.hasInitializer()) {
|
||||
result.add(var);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
protected List<DefinedVariable> definedGlobalScopeVariables() {
|
||||
List<DefinedVariable> result = new ArrayList<DefinedVariable>();
|
||||
for (Entity ent : entities.values()) {
|
||||
if (ent instanceof DefinedVariable) {
|
||||
result.add((DefinedVariable)ent);
|
||||
}
|
||||
}
|
||||
result.addAll(staticLocalVariables());
|
||||
return result;
|
||||
}
|
||||
|
||||
protected List<DefinedVariable> staticLocalVariables() {
|
||||
if (staticLocalVariables == null) {
|
||||
staticLocalVariables = new ArrayList<DefinedVariable>();
|
||||
for (LocalScope s : children) {
|
||||
staticLocalVariables.addAll(s.staticLocalVariables());
|
||||
}
|
||||
Map<String, Integer> seqTable = new HashMap<String, Integer>();
|
||||
for (DefinedVariable var : staticLocalVariables) {
|
||||
Integer seq = seqTable.get(var.name());
|
||||
if (seq == null) {
|
||||
var.setSequence(0);
|
||||
seqTable.put(var.name(), 1);
|
||||
}
|
||||
else {
|
||||
var.setSequence(seq);
|
||||
seqTable.put(var.name(), seq + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return staticLocalVariables;
|
||||
}
|
||||
|
||||
public void checkReferences(ErrorHandler h) {
|
||||
for (Entity ent : entities.values()) {
|
||||
if (ent.isDefined() && ent.isPrivate() && !ent.isRefered()) {
|
||||
h.warn(ent.location(), "unused variable: " + ent.name());
|
||||
}
|
||||
}
|
||||
// do not check parameters
|
||||
for (LocalScope funcScope : children) {
|
||||
for (LocalScope s : funcScope.children) {
|
||||
s.checkReferences(h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,12 +6,12 @@ import java.util.*;
|
|||
public class UndefinedFunction extends Function {
|
||||
protected Params params;
|
||||
|
||||
public UndefinedFunction(TypeNode t, String name, Params ps) {
|
||||
public UndefinedFunction(TypeNode t, String name, Params params) {
|
||||
super(false, t, name);
|
||||
params = ps;
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public Iterator parameters() {
|
||||
public List<Parameter> parameters() {
|
||||
return params.parameters();
|
||||
}
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@ import net.loveruby.cflat.type.*;
|
|||
import java.util.*;
|
||||
|
||||
public class UnionNode extends CompositeTypeDefinition {
|
||||
public UnionNode(Location loc, TypeRef ref, String name, List membs) {
|
||||
public UnionNode(Location loc, TypeRef ref, String name, List<Slot> membs) {
|
||||
super(loc, ref, name, membs);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
package net.loveruby.cflat.ast;
|
||||
import net.loveruby.cflat.type.*;
|
||||
import java.util.*;
|
||||
|
||||
public class VarParams extends Params {
|
||||
protected FixedParams params;
|
||||
|
||||
public VarParams(FixedParams params) {
|
||||
super();
|
||||
this.params = params;
|
||||
}
|
||||
|
||||
public Iterator parameters() {
|
||||
return params.parameters();
|
||||
}
|
||||
|
||||
public int argc() {
|
||||
throw new Error("VarParams#argc");
|
||||
}
|
||||
|
||||
public int minArgc() {
|
||||
return params.minArgc();
|
||||
}
|
||||
|
||||
public boolean isVararg() {
|
||||
return true;
|
||||
}
|
||||
|
||||
protected FixedParams fixedParams() {
|
||||
return params;
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof VarParams)) return false;
|
||||
VarParams params = (VarParams)other;
|
||||
return params.equals(params.fixedParams());
|
||||
}
|
||||
|
||||
public Params internTypes(TypeTable table) {
|
||||
return new VarParams((FixedParams)params.internTypes(table));
|
||||
}
|
||||
|
||||
public Params typeRefs() {
|
||||
return new VarParams((FixedParams)params.typeRefs());
|
||||
}
|
||||
|
||||
public Iterator types() {
|
||||
return params.types();
|
||||
}
|
||||
|
||||
public boolean isSameType(Params other) {
|
||||
if (!other.isVararg()) return false;
|
||||
VarParams otherParams = (VarParams)other;
|
||||
return this.fixedParams().isSameType(otherParams.fixedParams());
|
||||
}
|
||||
|
||||
public Location location() {
|
||||
return params.location();
|
||||
}
|
||||
}
|
|
@ -9,7 +9,7 @@ public class CodeGenerator
|
|||
// #@@range/ctor{
|
||||
protected CodeGeneratorOptions options;
|
||||
protected ErrorHandler errorHandler;
|
||||
protected LinkedList asStack;
|
||||
protected LinkedList<Assembler> asStack;
|
||||
protected Assembler as;
|
||||
protected TypeTable typeTable;
|
||||
protected DefinedFunction currentFunction;
|
||||
|
@ -18,7 +18,7 @@ public class CodeGenerator
|
|||
ErrorHandler errorHandler) {
|
||||
this.options = options;
|
||||
this.errorHandler = errorHandler;
|
||||
this.asStack = new LinkedList();
|
||||
this.asStack = new LinkedList<Assembler>();
|
||||
}
|
||||
// #@@}
|
||||
|
||||
|
@ -27,22 +27,28 @@ public class CodeGenerator
|
|||
public String generate(AST ast) {
|
||||
this.typeTable = ast.typeTable();
|
||||
pushAssembler();
|
||||
resolveConstants(ast.constantTable());
|
||||
resolveGlobalVariables(ast.allGlobalVariables());
|
||||
resolveFunctions(ast.allFunctions());
|
||||
for (ConstantEntry ent : ast.constantTable().entries()) {
|
||||
locateConstant(ent);
|
||||
}
|
||||
for (Variable var : ast.allGlobalVariables()) {
|
||||
locateGlobalVariable(var);
|
||||
}
|
||||
for (Function func : ast.allFunctions()) {
|
||||
locateFunction(func);
|
||||
}
|
||||
compileAST(ast);
|
||||
return popAssembler().toSource();
|
||||
}
|
||||
|
||||
protected void pushAssembler() {
|
||||
asStack.add(newAssembler());
|
||||
this.as = (Assembler)asStack.getLast();
|
||||
this.as = newAssembler();
|
||||
asStack.add(this.as);
|
||||
}
|
||||
|
||||
protected Assembler popAssembler() {
|
||||
Assembler poped = (Assembler)asStack.removeLast();
|
||||
this.as = asStack.isEmpty() ? null : (Assembler)asStack.getLast();
|
||||
return poped;
|
||||
Assembler popped = asStack.removeLast();
|
||||
this.as = asStack.isEmpty() ? null : asStack.getLast();
|
||||
return popped;
|
||||
}
|
||||
|
||||
protected Assembler newAssembler() {
|
||||
|
@ -53,18 +59,26 @@ public class CodeGenerator
|
|||
_file(ast.fileName());
|
||||
// .data
|
||||
_data();
|
||||
compileGlobalVariables(ast.globalVariables());
|
||||
for (DefinedVariable gvar : ast.definedGlobalVariables()) {
|
||||
dataEntry(gvar);
|
||||
}
|
||||
if (!ast.constantTable().isEmpty()) {
|
||||
_section(".rodata");
|
||||
compileConstants(ast.constantTable());
|
||||
for (ConstantEntry ent : ast.constantTable()) {
|
||||
compileStringLiteral(ent);
|
||||
}
|
||||
}
|
||||
// .text
|
||||
if (ast.functionDefined()) {
|
||||
_text();
|
||||
compileFunctions(ast.functions());
|
||||
for (DefinedFunction func : ast.definedFunctions()) {
|
||||
compileFunction(func);
|
||||
}
|
||||
}
|
||||
// .bss
|
||||
compileCommonSymbols(ast.commonSymbols());
|
||||
for (DefinedVariable var : ast.definedCommonSymbols()) {
|
||||
compileCommonSymbol(var);
|
||||
}
|
||||
// others
|
||||
if (options.isPICRequired()) {
|
||||
PICThunk(GOTBaseReg());
|
||||
|
@ -72,40 +86,19 @@ public class CodeGenerator
|
|||
}
|
||||
// #@@}
|
||||
|
||||
protected void resolveConstants(ConstantTable table) {
|
||||
Iterator ents = table.entries();
|
||||
while (ents.hasNext()) {
|
||||
ConstantEntry ent = (ConstantEntry)ents.next();
|
||||
ent.setLabel(new Label(".LC" + ent.id()));
|
||||
if (options.isPICRequired()) {
|
||||
Label offset = new Label(localGOTSymbol(ent.symbol()));
|
||||
ent.setMemref(mem(offset, GOTBaseReg()));
|
||||
}
|
||||
else {
|
||||
ent.setMemref(mem(ent.label()));
|
||||
ent.setAddress(imm(ent.label()));
|
||||
}
|
||||
protected void locateConstant(ConstantEntry ent) {
|
||||
ent.setLabel(new Label(".LC" + ent.id()));
|
||||
if (options.isPICRequired()) {
|
||||
Label offset = new Label(localGOTSymbol(ent.symbol()));
|
||||
ent.setMemref(mem(offset, GOTBaseReg()));
|
||||
}
|
||||
else {
|
||||
ent.setMemref(mem(ent.label()));
|
||||
ent.setAddress(imm(ent.label()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets memory reference for...
|
||||
* * public global variables
|
||||
* * private global variables
|
||||
* * public common symbols
|
||||
* * private common symbols
|
||||
* * static local variables
|
||||
*/
|
||||
// #@@range/resolveGlobalVariables
|
||||
protected void resolveGlobalVariables(Iterator vars) {
|
||||
while (vars.hasNext()) {
|
||||
Variable var = (Variable)vars.next();
|
||||
resolveGlobalVariable(var);
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
||||
protected void resolveGlobalVariable(Variable var) {
|
||||
protected void locateGlobalVariable(Variable var) {
|
||||
String sym = var.symbol();
|
||||
MemoryReference mem;
|
||||
if (options.isPICRequired()) {
|
||||
|
@ -124,12 +117,9 @@ public class CodeGenerator
|
|||
}
|
||||
}
|
||||
|
||||
protected void resolveFunctions(Iterator funcs) {
|
||||
while (funcs.hasNext()) {
|
||||
Function func = (Function)funcs.next();
|
||||
func.setSymbol(functionSymbol(func));
|
||||
func.setAddress(functionAddress(func));
|
||||
}
|
||||
protected void locateFunction(Function func) {
|
||||
func.setSymbol(functionSymbol(func));
|
||||
func.setAddress(functionAddress(func));
|
||||
}
|
||||
|
||||
protected String functionSymbol(Function func) {
|
||||
|
@ -161,16 +151,6 @@ public class CodeGenerator
|
|||
}
|
||||
}
|
||||
|
||||
/** Generates static variable entries */
|
||||
// #@@range/compileGlobalVariables{
|
||||
protected void compileGlobalVariables(Iterator vars) {
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
dataEntry(var);
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
||||
/** Generates initialized entries */
|
||||
// #@@range/dataEntry{
|
||||
protected void dataEntry(DefinedVariable ent) {
|
||||
|
@ -215,27 +195,20 @@ public class CodeGenerator
|
|||
// #@@}
|
||||
|
||||
/** Generates BSS entries */
|
||||
// #@@range/compileCommonSymbols{
|
||||
protected void compileCommonSymbols(Iterator ents) {
|
||||
while (ents.hasNext()) {
|
||||
Variable ent = (Variable)ents.next();
|
||||
if (ent.isPrivate()) {
|
||||
_local(csymbol(ent.symbol()));
|
||||
}
|
||||
_comm(csymbol(ent.symbol()), ent.allocSize(), ent.alignment());
|
||||
// #@@range/compileCommonSymbol{
|
||||
protected void compileCommonSymbol(DefinedVariable var) {
|
||||
if (var.isPrivate()) {
|
||||
_local(csymbol(var.symbol()));
|
||||
}
|
||||
_comm(csymbol(var.symbol()), var.allocSize(), var.alignment());
|
||||
}
|
||||
// #@@}
|
||||
|
||||
/** Generates .rodata entry (constant strings) */
|
||||
// #@@range/compileConstants{
|
||||
protected void compileConstants(ConstantTable table) {
|
||||
Iterator ents = table.entries();
|
||||
while (ents.hasNext()) {
|
||||
ConstantEntry ent = (ConstantEntry)ents.next();
|
||||
label(ent.label());
|
||||
_string(ent.value());
|
||||
}
|
||||
// #@@range/compileStringLiteral{
|
||||
protected void compileStringLiteral(ConstantEntry ent) {
|
||||
label(ent.label());
|
||||
_string(ent.value());
|
||||
}
|
||||
// #@@}
|
||||
|
||||
|
@ -317,15 +290,6 @@ public class CodeGenerator
|
|||
// Compile Function
|
||||
//
|
||||
|
||||
/** Compiles all functions and generates .text section. */
|
||||
// #@@range/compileFunctions{
|
||||
protected void compileFunctions(Iterator funcs) {
|
||||
while (funcs.hasNext()) {
|
||||
compileFunction((DefinedFunction)funcs.next());
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
||||
/** Compiles a function. */
|
||||
// #@@range/compileFunction{
|
||||
protected void compileFunction(DefinedFunction func) {
|
||||
|
@ -344,10 +308,10 @@ public class CodeGenerator
|
|||
// #@@}
|
||||
|
||||
protected void compileFunctionBody(DefinedFunction func) {
|
||||
List bodyAsms = compileStmts(func);
|
||||
List<Assembly> bodyAsms = compileStmts(func);
|
||||
AsmStatistics stats = AsmStatistics.collect(bodyAsms);
|
||||
bodyAsms = reduceLabels(bodyAsms, stats);
|
||||
List saveRegs = usedCalleeSavedRegisters(stats);
|
||||
List<Register> saveRegs = usedCalleeSavedRegisters(stats);
|
||||
long lvarBytes = allocateLocalVariables(func.body().scope(),
|
||||
saveRegs.size());
|
||||
prologue(func, saveRegs, lvarBytes);
|
||||
|
@ -358,7 +322,7 @@ public class CodeGenerator
|
|||
epilogue(func, saveRegs, lvarBytes);
|
||||
}
|
||||
|
||||
protected List compileStmts(DefinedFunction func) {
|
||||
protected List<Assembly> compileStmts(DefinedFunction func) {
|
||||
pushAssembler();
|
||||
currentFunction = func;
|
||||
compile(func.body());
|
||||
|
@ -367,11 +331,9 @@ public class CodeGenerator
|
|||
return options.optimizer().optimize(popAssembler().assemblies());
|
||||
}
|
||||
|
||||
protected List reduceLabels(List assemblies, AsmStatistics stats) {
|
||||
List result = new ArrayList();
|
||||
Iterator asms = assemblies.iterator();
|
||||
while (asms.hasNext()) {
|
||||
Assembly asm = (Assembly)asms.next();
|
||||
protected List<Assembly> reduceLabels(List<Assembly> assemblies, AsmStatistics stats) {
|
||||
List<Assembly> result = new ArrayList<Assembly>();
|
||||
for (Assembly asm : assemblies) {
|
||||
if (asm.isLabel() && ! stats.doesLabelUsed((Label)asm)) {
|
||||
;
|
||||
}
|
||||
|
@ -396,11 +358,9 @@ public class CodeGenerator
|
|||
}
|
||||
// #@@}
|
||||
|
||||
protected List usedCalleeSavedRegisters(AsmStatistics stats) {
|
||||
List result = new ArrayList();
|
||||
Iterator regs = calleeSavedRegisters().iterator();
|
||||
while (regs.hasNext()) {
|
||||
Register reg = (Register)regs.next();
|
||||
protected List<Register> usedCalleeSavedRegisters(AsmStatistics stats) {
|
||||
List<Register> result = new ArrayList<Register>();
|
||||
for (Register reg : calleeSavedRegisters()) {
|
||||
if (stats.doesRegisterUsed(reg)) {
|
||||
result.add(reg);
|
||||
}
|
||||
|
@ -408,11 +368,11 @@ public class CodeGenerator
|
|||
return result;
|
||||
}
|
||||
|
||||
protected List calleeSavedRegistersCache = null;
|
||||
protected List<Register> calleeSavedRegistersCache = null;
|
||||
|
||||
protected List calleeSavedRegisters() {
|
||||
protected List<Register> calleeSavedRegisters() {
|
||||
if (calleeSavedRegistersCache == null) {
|
||||
ArrayList regs = new ArrayList();
|
||||
List<Register> regs = new ArrayList<Register>();
|
||||
regs.add(reg("bx"));
|
||||
regs.add(reg("si"));
|
||||
regs.add(reg("di"));
|
||||
|
@ -461,15 +421,14 @@ public class CodeGenerator
|
|||
|
||||
// #@@range/prologue{
|
||||
protected void prologue(DefinedFunction func,
|
||||
List saveRegs, long lvarBytes) {
|
||||
List<Register> saveRegs,
|
||||
long lvarBytes) {
|
||||
push(bp());
|
||||
mov(sp(), bp());
|
||||
saveRegisters(saveRegs);
|
||||
extendStack(lvarBytes);
|
||||
if (options.isVerboseAsm()) {
|
||||
Iterator vars = func.localVariables();
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
for (DefinedVariable var : func.localVariables()) {
|
||||
comment("mem " + var.memref().toSource() + ": " + var.name());
|
||||
}
|
||||
}
|
||||
|
@ -478,7 +437,8 @@ public class CodeGenerator
|
|||
|
||||
// #@@range/epilogue{
|
||||
protected void epilogue(DefinedFunction func,
|
||||
List savedRegs, long lvarBytes) {
|
||||
List<Register> savedRegs,
|
||||
long lvarBytes) {
|
||||
shrinkStack(lvarBytes);
|
||||
restoreRegisters(savedRegs);
|
||||
mov(bp(), sp());
|
||||
|
@ -487,20 +447,18 @@ public class CodeGenerator
|
|||
}
|
||||
// #@@}
|
||||
|
||||
protected void saveRegisters(List saveRegs) {
|
||||
Iterator regs = saveRegs.iterator();
|
||||
while (regs.hasNext()) {
|
||||
Register reg = (Register)regs.next();
|
||||
protected void saveRegisters(List<Register> saveRegs) {
|
||||
for (Register reg : saveRegs) {
|
||||
if (! reg.equals(bp())) { // bp is already saved.
|
||||
push(reg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void restoreRegisters(List savedRegs) {
|
||||
Iterator regs = savedRegs.iterator();
|
||||
while (regs.hasNext()) {
|
||||
Register reg = (Register)regs.next();
|
||||
protected void restoreRegisters(List<Register> savedRegs) {
|
||||
ListIterator<Register> regs = savedRegs.listIterator(savedRegs.size());
|
||||
while (regs.hasPrevious()) {
|
||||
Register reg = regs.previous();
|
||||
if (! reg.equals(bp())) { // bp is going to be restored.
|
||||
pop(reg);
|
||||
}
|
||||
|
@ -520,10 +478,8 @@ public class CodeGenerator
|
|||
// #@@}
|
||||
|
||||
protected void allocateParameters(DefinedFunction func) {
|
||||
Iterator vars = func.parameters();
|
||||
long word = paramStartWord;
|
||||
while (vars.hasNext()) {
|
||||
Parameter var = (Parameter)vars.next();
|
||||
for (Parameter var : func.parameters()) {
|
||||
if (stackGrowsLower) {
|
||||
var.setMemref(mem(word * stackWordSize, bp()));
|
||||
}
|
||||
|
@ -539,9 +495,7 @@ public class CodeGenerator
|
|||
* not determined, assign unfixed IndirectMemoryReference.
|
||||
*/
|
||||
protected void allocateLocalVariablesTemp(LocalScope scope) {
|
||||
Iterator vars = scope.allLocalVariables();
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
for (DefinedVariable var : scope.allLocalVariables()) {
|
||||
var.setMemref(new IndirectMemoryReference(bp()));
|
||||
}
|
||||
}
|
||||
|
@ -559,9 +513,7 @@ public class CodeGenerator
|
|||
|
||||
protected long allocateScope(LocalScope scope, long parentStackLen) {
|
||||
long len = parentStackLen;
|
||||
Iterator vars = scope.variables();
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
for (DefinedVariable var : scope.localVariables()) {
|
||||
if (stackGrowsLower) {
|
||||
len = Assembler.align(len + var.allocSize(), stackAlignment);
|
||||
fixMemref((IndirectMemoryReference)var.memref(), -len);
|
||||
|
@ -574,9 +526,7 @@ public class CodeGenerator
|
|||
// Allocate local variables in child scopes.
|
||||
// We allocate child scopes in the same area (overrapped).
|
||||
long maxLen = len;
|
||||
Iterator scopes = scope.children();
|
||||
while (scopes.hasNext()) {
|
||||
LocalScope s = (LocalScope)scopes.next();
|
||||
for (LocalScope s : scope.children()) {
|
||||
long childLen = allocateScope(s, len);
|
||||
maxLen = Math.max(maxLen, childLen);
|
||||
}
|
||||
|
@ -606,10 +556,9 @@ public class CodeGenerator
|
|||
*/
|
||||
public void visit(FuncallNode node) {
|
||||
// compile function arguments from right to left.
|
||||
ListIterator args = node.finalArg();
|
||||
ListIterator<ExprNode> args = node.finalArg();
|
||||
while (args.hasPrevious()) {
|
||||
ExprNode arg = (ExprNode)args.previous();
|
||||
compile(arg);
|
||||
compile(args.previous());
|
||||
push(reg("ax"));
|
||||
}
|
||||
// call
|
||||
|
@ -639,17 +588,14 @@ public class CodeGenerator
|
|||
//
|
||||
|
||||
public void visit(BlockNode node) {
|
||||
Iterator vars = node.scope().variables();
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
for (DefinedVariable var : node.scope().localVariables()) {
|
||||
if (var.initializer() != null) {
|
||||
compile(var.initializer());
|
||||
save(var.type(), reg("ax"), var.memref());
|
||||
}
|
||||
}
|
||||
Iterator stmts = node.stmts();
|
||||
while (stmts.hasNext()) {
|
||||
compileStmt((Node)stmts.next());
|
||||
for (Node stmt : node.stmts()) {
|
||||
compileStmt(stmt);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -696,26 +642,22 @@ public class CodeGenerator
|
|||
public void visit(SwitchNode node) {
|
||||
compile(node.cond());
|
||||
Type t = typeTable.signedInt();
|
||||
Iterator cases = node.cases();
|
||||
while (cases.hasNext()) {
|
||||
CaseNode caseNode = (CaseNode)cases.next();
|
||||
if (! caseNode.isDefault()) {
|
||||
Iterator values = caseNode.values();
|
||||
while (values.hasNext()) {
|
||||
IntegerLiteralNode ival = (IntegerLiteralNode)values.next();
|
||||
for (CaseNode cn : node.cases()) {
|
||||
if (! cn.isDefault()) {
|
||||
for (ExprNode ex : cn.values()) {
|
||||
IntegerLiteralNode ival = (IntegerLiteralNode)ex;
|
||||
mov(imm(ival.value()), reg("cx"));
|
||||
cmp(t, reg("cx", t), reg("ax", t));
|
||||
je(caseNode.beginLabel());
|
||||
je(cn.beginLabel());
|
||||
}
|
||||
}
|
||||
else {
|
||||
jmp(caseNode.beginLabel());
|
||||
jmp(cn.beginLabel());
|
||||
}
|
||||
}
|
||||
jmp(node.endLabel());
|
||||
cases = node.cases();
|
||||
while (cases.hasNext()) {
|
||||
compile((CaseNode)cases.next());
|
||||
for (CaseNode n : node.cases()) {
|
||||
compile(n);
|
||||
}
|
||||
label(node.endLabel());
|
||||
}
|
||||
|
|
|
@ -29,7 +29,9 @@ class CodeGeneratorOptions {
|
|||
}
|
||||
|
||||
class NullOptimizer implements AsmOptimizer {
|
||||
public List optimize(List assemblies) { return assemblies; }
|
||||
public List<Assembly> optimize(List<Assembly> asms) {
|
||||
return asms;
|
||||
}
|
||||
}
|
||||
|
||||
public void generateVerboseAsm() {
|
||||
|
|
|
@ -27,7 +27,7 @@ public class Compiler {
|
|||
|
||||
public void commandMain(String[] origArgs) {
|
||||
Options opts = new Options(defaultTypeTable(), new LibraryLoader());
|
||||
List srcs = null;
|
||||
List<SourceFile> srcs = null;
|
||||
try {
|
||||
srcs = opts.parse(Arrays.asList(origArgs));
|
||||
}
|
||||
|
@ -37,10 +37,8 @@ public class Compiler {
|
|||
System.exit(1);
|
||||
}
|
||||
if (opts.isMode("--check-syntax")) {
|
||||
Iterator inputs = srcs.iterator();
|
||||
boolean failed = false;
|
||||
while (inputs.hasNext()) {
|
||||
SourceFile src = (SourceFile)inputs.next();
|
||||
for (SourceFile src : srcs) {
|
||||
if (isValidSyntax(src, opts)) {
|
||||
System.out.println(src.name() + ": Syntax OK");
|
||||
}
|
||||
|
@ -53,9 +51,7 @@ public class Compiler {
|
|||
}
|
||||
else {
|
||||
try {
|
||||
Iterator inputs = srcs.iterator();
|
||||
while (inputs.hasNext()) {
|
||||
SourceFile src = (SourceFile)inputs.next();
|
||||
for (SourceFile src : srcs) {
|
||||
compileFile(src, opts);
|
||||
}
|
||||
if (! opts.isLinkRequired()) System.exit(0);
|
||||
|
@ -134,9 +130,8 @@ public class Compiler {
|
|||
}
|
||||
}
|
||||
|
||||
protected void dumpTokens(Iterator tokens, PrintStream s) {
|
||||
while (tokens.hasNext()) {
|
||||
CflatToken t = (CflatToken)tokens.next();
|
||||
protected void dumpTokens(CflatToken tokens, PrintStream s) {
|
||||
for (CflatToken t : tokens) {
|
||||
printPair(t.kindName(), t.dumpedImage(), s);
|
||||
}
|
||||
}
|
||||
|
@ -152,15 +147,13 @@ public class Compiler {
|
|||
}
|
||||
|
||||
protected Node findStmt(AST ast) {
|
||||
Iterator funcs = ast.functions();
|
||||
while (funcs.hasNext()) {
|
||||
DefinedFunction f = (DefinedFunction)funcs.next();
|
||||
for (DefinedFunction f : ast.definedFunctions()) {
|
||||
if (f.name().equals("main")) {
|
||||
Iterator stmts = f.body().stmts();
|
||||
while (stmts.hasNext()) {
|
||||
return (Node)stmts.next();
|
||||
Node stmt = f.body().stmts().get(0);
|
||||
if (stmt == null) {
|
||||
errorExit("main() has no stmt");
|
||||
}
|
||||
errorExit("main() has no stmt");
|
||||
return stmt;
|
||||
}
|
||||
}
|
||||
errorExit("source file does not contains main()");
|
||||
|
@ -197,7 +190,7 @@ public class Compiler {
|
|||
protected void assemble(String srcPath,
|
||||
String destPath,
|
||||
Options opts) throws IPCException {
|
||||
List cmd = new ArrayList();
|
||||
List<Object> cmd = new ArrayList<Object>();
|
||||
cmd.add("as");
|
||||
cmd.addAll(opts.asOptions());
|
||||
cmd.add("-o");
|
||||
|
@ -213,7 +206,7 @@ public class Compiler {
|
|||
static final protected String C_RUNTIME_FINI = "/usr/lib/crtn.o";
|
||||
|
||||
protected void generateExecutable(Options opts) throws IPCException {
|
||||
List cmd = new ArrayList();
|
||||
List<Object> cmd = new ArrayList<Object>();
|
||||
cmd.add("ld");
|
||||
cmd.add("-dynamic-linker");
|
||||
cmd.add(DYNAMIC_LINKER);
|
||||
|
@ -240,7 +233,7 @@ public class Compiler {
|
|||
}
|
||||
|
||||
protected void generateSharedLibrary(Options opts) throws IPCException {
|
||||
List cmd = new ArrayList();
|
||||
List<Object> cmd = new ArrayList<Object>();
|
||||
cmd.add("ld");
|
||||
cmd.add("-shared");
|
||||
if (! opts.noStartFiles()) {
|
||||
|
@ -259,12 +252,12 @@ public class Compiler {
|
|||
invoke(cmd, opts.isVerboseMode());
|
||||
}
|
||||
|
||||
protected void invoke(List cmdArgs, boolean debug) throws IPCException {
|
||||
protected void invoke(List<Object> cmdArgs, boolean debug) throws IPCException {
|
||||
if (debug) {
|
||||
dumpCommand(cmdArgs.iterator());
|
||||
dumpCommand(cmdArgs);
|
||||
}
|
||||
try {
|
||||
String[] cmd = stringListToArray(cmdArgs);
|
||||
String[] cmd = getStrings(cmdArgs);
|
||||
Process proc = Runtime.getRuntime().exec(cmd);
|
||||
proc.waitFor();
|
||||
passThrough(proc.getInputStream());
|
||||
|
@ -285,23 +278,20 @@ public class Compiler {
|
|||
}
|
||||
}
|
||||
|
||||
protected String[] stringListToArray(List list) {
|
||||
protected String[] getStrings(List<Object> list) {
|
||||
String[] a = new String[list.size()];
|
||||
int idx = 0;
|
||||
Iterator it = list.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object o = it.next();
|
||||
for (Object o : list) {
|
||||
a[idx++] = o.toString();
|
||||
}
|
||||
return a;
|
||||
}
|
||||
|
||||
protected void dumpCommand(Iterator args) {
|
||||
protected void dumpCommand(List<Object> args) {
|
||||
String sep = "";
|
||||
while (args.hasNext()) {
|
||||
String arg = args.next().toString();
|
||||
for (Object arg : args) {
|
||||
System.out.print(sep); sep = " ";
|
||||
System.out.print(arg);
|
||||
System.out.print(arg.toString());
|
||||
}
|
||||
System.out.println("");
|
||||
}
|
||||
|
|
|
@ -12,18 +12,12 @@ class DereferenceChecker extends Visitor {
|
|||
}
|
||||
|
||||
public void check(AST ast) throws SemanticException {
|
||||
Iterator vars = ast.variables();
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
for (DefinedVariable var : ast.definedVariables()) {
|
||||
checkVariable(var);
|
||||
}
|
||||
|
||||
Iterator funcs = ast.functions();
|
||||
while (funcs.hasNext()) {
|
||||
DefinedFunction f = (DefinedFunction)funcs.next();
|
||||
for (DefinedFunction f : ast.definedFunctions()) {
|
||||
check(f.body());
|
||||
}
|
||||
|
||||
if (errorHandler.errorOccured()) {
|
||||
throw new SemanticException("compile failed.");
|
||||
}
|
||||
|
@ -38,15 +32,10 @@ class DereferenceChecker extends Visitor {
|
|||
//
|
||||
|
||||
public void visit(BlockNode node) {
|
||||
Iterator vars = node.variables();
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
for (DefinedVariable var : node.variables()) {
|
||||
checkVariable(var);
|
||||
}
|
||||
|
||||
Iterator stmts = node.stmts();
|
||||
while (stmts.hasNext()) {
|
||||
Node stmt = (Node)stmts.next();
|
||||
for (Node stmt : node.stmts()) {
|
||||
try {
|
||||
check(stmt);
|
||||
}
|
||||
|
@ -79,7 +68,7 @@ class DereferenceChecker extends Visitor {
|
|||
public void visit(OpAssignNode node) {
|
||||
super.visit(node);
|
||||
checkAssignment(node);
|
||||
// check as operator
|
||||
// FIXME: check as operator
|
||||
}
|
||||
|
||||
protected void checkAssignment(AbstractAssignNode node) {
|
||||
|
|
|
@ -7,8 +7,8 @@ import java.util.*;
|
|||
public class JumpResolver extends Visitor {
|
||||
// #@@range/ctor{
|
||||
protected ErrorHandler errorHandler;
|
||||
protected LinkedList breakTargetStack;
|
||||
protected LinkedList continueTargetStack;
|
||||
protected LinkedList<BreakableStmt> breakTargetStack;
|
||||
protected LinkedList<ContinueableStmt> continueTargetStack;
|
||||
protected DefinedFunction currentFunction;
|
||||
|
||||
public JumpResolver(ErrorHandler h) {
|
||||
|
@ -18,13 +18,12 @@ public class JumpResolver extends Visitor {
|
|||
|
||||
// #@@range/resolve{
|
||||
public void resolve(AST ast) throws SemanticException {
|
||||
breakTargetStack = new LinkedList();
|
||||
continueTargetStack = new LinkedList();
|
||||
Iterator funcs = ast.functions();
|
||||
while (funcs.hasNext()) {
|
||||
currentFunction = (DefinedFunction)funcs.next();
|
||||
resolve(currentFunction.body());
|
||||
currentFunction.checkJumpLinks(errorHandler);
|
||||
breakTargetStack = new LinkedList<BreakableStmt>();
|
||||
continueTargetStack = new LinkedList<ContinueableStmt>();
|
||||
for (DefinedFunction f : ast.definedFunctions()) {
|
||||
currentFunction = f;
|
||||
resolve(f.body());
|
||||
f.checkJumpLinks(errorHandler);
|
||||
}
|
||||
if (errorHandler.errorOccured()) {
|
||||
throw new SemanticException("compile failed.");
|
||||
|
@ -83,7 +82,7 @@ public class JumpResolver extends Visitor {
|
|||
"break from out of while/do-while/for/switch");
|
||||
return;
|
||||
}
|
||||
BreakableStmt target = (BreakableStmt)breakTargetStack.getLast();
|
||||
BreakableStmt target = breakTargetStack.getLast();
|
||||
node.setTargetLabel(target.endLabel());
|
||||
}
|
||||
// #@@}
|
||||
|
@ -95,8 +94,7 @@ public class JumpResolver extends Visitor {
|
|||
"continue from out of while/do-while/for");
|
||||
return;
|
||||
}
|
||||
ContinueableStmt target =
|
||||
(ContinueableStmt)continueTargetStack.getLast();
|
||||
ContinueableStmt target = continueTargetStack.getLast();
|
||||
node.setTargetLabel(target.continueLabel());
|
||||
}
|
||||
// #@@}
|
||||
|
|
|
@ -6,12 +6,12 @@ import java.util.*;
|
|||
import java.io.*;
|
||||
|
||||
public class LibraryLoader {
|
||||
protected List loadPath;
|
||||
protected LinkedList loadingLibraries; // LinkedList<String>
|
||||
protected Map loadedLibraries; // Map<String, Boolean>
|
||||
protected List<String> loadPath;
|
||||
protected LinkedList<String> loadingLibraries;
|
||||
protected Map<String, Declarations> loadedLibraries;
|
||||
|
||||
static public List defaultLoadPath() {
|
||||
List pathes = new ArrayList();
|
||||
static public List<String> defaultLoadPath() {
|
||||
List<String> pathes = new ArrayList<String>();
|
||||
pathes.add(".");
|
||||
return pathes;
|
||||
}
|
||||
|
@ -20,10 +20,10 @@ public class LibraryLoader {
|
|||
this(defaultLoadPath());
|
||||
}
|
||||
|
||||
public LibraryLoader(List loadPath) {
|
||||
public LibraryLoader(List<String> loadPath) {
|
||||
this.loadPath = loadPath;
|
||||
this.loadingLibraries = new LinkedList();
|
||||
this.loadedLibraries = new HashMap();
|
||||
this.loadingLibraries = new LinkedList<String>();
|
||||
this.loadedLibraries = new HashMap<String, Declarations>();
|
||||
}
|
||||
|
||||
public void addLoadPath(String path) {
|
||||
|
@ -38,7 +38,7 @@ public class LibraryLoader {
|
|||
+ ": " + libid);
|
||||
}
|
||||
loadingLibraries.addLast(libid); // stop recursive import
|
||||
Declarations decls = (Declarations)loadedLibraries.get(libid);
|
||||
Declarations decls = loadedLibraries.get(libid);
|
||||
if (decls != null) {
|
||||
// Already loaded import file. Returns cached declarations.
|
||||
return decls;
|
||||
|
@ -51,9 +51,7 @@ public class LibraryLoader {
|
|||
|
||||
public File searchLibrary(String libid) throws FileException {
|
||||
try {
|
||||
Iterator pathes = loadPath.iterator();
|
||||
while (pathes.hasNext()) {
|
||||
String path = (String)pathes.next();
|
||||
for (String path : loadPath) {
|
||||
File file = new File(path + "/" + libPath(libid) + ".hb");
|
||||
if (file.exists()) {
|
||||
return file;
|
||||
|
|
|
@ -7,7 +7,7 @@ public class LocalReferenceResolver extends Visitor {
|
|||
// #@@range/ctor{
|
||||
protected ErrorHandler errorHandler;
|
||||
protected ToplevelScope toplevel;
|
||||
protected LinkedList scopeStack;
|
||||
protected LinkedList<Scope> scopeStack;
|
||||
protected ConstantTable constantTable;
|
||||
|
||||
public LocalReferenceResolver(ErrorHandler h) {
|
||||
|
@ -22,17 +22,21 @@ public class LocalReferenceResolver extends Visitor {
|
|||
// #@@range/resolve{
|
||||
public void resolve(AST ast) throws SemanticException {
|
||||
toplevel = ast.scope();
|
||||
scopeStack = new LinkedList();
|
||||
scopeStack = new LinkedList<Scope>();
|
||||
scopeStack.add(toplevel);
|
||||
constantTable = ast.constantTable();
|
||||
|
||||
// #@@range/declareToplevel{
|
||||
declareToplevelEntities(ast.declarations());
|
||||
declareToplevelEntities(ast.entities());
|
||||
for (Entity decl : ast.declarations()) {
|
||||
toplevel.declareEntity(decl);
|
||||
}
|
||||
for (Entity ent : ast.entities()) {
|
||||
toplevel.declareEntity(ent);
|
||||
}
|
||||
// #@@}
|
||||
// #@@range/resolveRefs{
|
||||
resolveGvarInitializers(ast.variables());
|
||||
resolveFunctions(ast.functions());
|
||||
resolveGvarInitializers(ast.definedVariables());
|
||||
resolveFunctions(ast.definedFunctions());
|
||||
// #@@}
|
||||
toplevel.checkReferences(errorHandler);
|
||||
if (errorHandler.errorOccured()) {
|
||||
|
@ -41,29 +45,19 @@ public class LocalReferenceResolver extends Visitor {
|
|||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/declareToplevelEntities{
|
||||
protected void declareToplevelEntities(Iterator decls) {
|
||||
while (decls.hasNext()) {
|
||||
toplevel.declareEntity((Entity)decls.next());
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/resolveGvarInitializers{
|
||||
protected void resolveGvarInitializers(Iterator vars) {
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
if (var.hasInitializer()) {
|
||||
resolve(var.initializer());
|
||||
protected void resolveGvarInitializers(List<DefinedVariable> gvars) {
|
||||
for (DefinedVariable gvar : gvars) {
|
||||
if (gvar.hasInitializer()) {
|
||||
resolve(gvar.initializer());
|
||||
}
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/resolveFunctions{
|
||||
protected void resolveFunctions(Iterator funcs) {
|
||||
while (funcs.hasNext()) {
|
||||
DefinedFunction func = (DefinedFunction)funcs.next();
|
||||
protected void resolveFunctions(List<DefinedFunction> funcs) {
|
||||
for (DefinedFunction func : funcs) {
|
||||
pushScope(func.parameters());
|
||||
resolve(func.body());
|
||||
func.setScope(popScope());
|
||||
|
@ -80,15 +74,14 @@ public class LocalReferenceResolver extends Visitor {
|
|||
// #@@}
|
||||
|
||||
// #@@range/pushScope{
|
||||
protected void pushScope(Iterator vars) {
|
||||
protected void pushScope(List<? extends DefinedVariable> vars) {
|
||||
LocalScope scope = new LocalScope(currentScope());
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
for (DefinedVariable var : vars) {
|
||||
if (scope.isDefinedLocally(var.name())) {
|
||||
error(var, "duplicated variable in scope: " + var.name());
|
||||
}
|
||||
else {
|
||||
scope.declareEntity(var);
|
||||
scope.defineVariable(var);
|
||||
}
|
||||
}
|
||||
scopeStack.addLast(scope);
|
||||
|
@ -103,7 +96,7 @@ public class LocalReferenceResolver extends Visitor {
|
|||
|
||||
// #@@range/currentScope{
|
||||
protected Scope currentScope() {
|
||||
return (Scope)scopeStack.getLast();
|
||||
return scopeStack.getLast();
|
||||
}
|
||||
// #@@}
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@ class Options {
|
|||
protected boolean verbose;
|
||||
protected boolean debugParser;
|
||||
protected CodeGeneratorOptions genOptions;
|
||||
protected List asOptions; // List<String>
|
||||
protected List<String> asOptions;
|
||||
protected boolean generatingSharedLibrary;
|
||||
protected boolean generatingPIE;
|
||||
protected List ldArgs; // List<LdArg>
|
||||
protected List<LdArg> ldArgs;
|
||||
protected boolean noStartFiles = false;
|
||||
protected boolean noDefaultLibs = false;
|
||||
|
||||
|
@ -25,10 +25,10 @@ class Options {
|
|||
this.typeTable = typeTable;
|
||||
this.loader = loader;
|
||||
this.genOptions = new CodeGeneratorOptions();
|
||||
this.asOptions = new ArrayList();
|
||||
this.asOptions = new ArrayList<String>();
|
||||
this.generatingSharedLibrary = false;
|
||||
this.generatingPIE = false;
|
||||
this.ldArgs = new ArrayList();
|
||||
this.ldArgs = new ArrayList<LdArg>();
|
||||
}
|
||||
|
||||
public boolean isMode(String m) {
|
||||
|
@ -44,12 +44,12 @@ class Options {
|
|||
}
|
||||
|
||||
static final protected String defaultMode = "link";
|
||||
static protected List modeLevels;
|
||||
static protected List<String> modeLevels;
|
||||
static final protected int MODE_LEVEL_ASSEMBLE;
|
||||
static final protected int MODE_LEVEL_LINK;
|
||||
|
||||
static {
|
||||
modeLevels = new ArrayList();
|
||||
modeLevels = new ArrayList<String>();
|
||||
modeLevels.add("--check-syntax");
|
||||
modeLevels.add("--dump-tokens");
|
||||
modeLevels.add("--dump-ast");
|
||||
|
@ -86,23 +86,20 @@ class Options {
|
|||
if (outputFileName != null) {
|
||||
return outputFileName;
|
||||
}
|
||||
List srcs = sourceFiles();
|
||||
List<SourceFile> srcs = sourceFiles();
|
||||
if (srcs.size() == 1) {
|
||||
SourceFile src = (SourceFile)srcs.get(0);
|
||||
return src.linkedFileName(this, newExt);
|
||||
return srcs.get(0).linkedFileName(this, newExt);
|
||||
}
|
||||
else {
|
||||
return "a.out";
|
||||
}
|
||||
}
|
||||
|
||||
protected List sourceFiles() {
|
||||
Iterator args = ldArgs.iterator();
|
||||
List result = new ArrayList();
|
||||
while (args.hasNext()) {
|
||||
LdArg arg = (LdArg)args.next();
|
||||
protected List<SourceFile> sourceFiles() {
|
||||
List<SourceFile> result = new ArrayList<SourceFile>();
|
||||
for (LdArg arg : ldArgs) {
|
||||
if (arg.isSourceFile()) {
|
||||
result.add(arg);
|
||||
result.add((SourceFile)arg);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
@ -132,8 +129,7 @@ class Options {
|
|||
return genOptions;
|
||||
}
|
||||
|
||||
// List<String>
|
||||
public List asOptions() {
|
||||
public List<String> asOptions() {
|
||||
return this.asOptions;
|
||||
}
|
||||
|
||||
|
@ -146,7 +142,7 @@ class Options {
|
|||
}
|
||||
|
||||
// List<ldArg>
|
||||
public List ldArgs() {
|
||||
public List<LdArg> ldArgs() {
|
||||
return this.ldArgs;
|
||||
}
|
||||
|
||||
|
@ -159,11 +155,11 @@ class Options {
|
|||
}
|
||||
|
||||
/** Returns List<SourceFile>. */
|
||||
public List parse(List argsList) {
|
||||
ListIterator args = argsList.listIterator();
|
||||
List srcs = new ArrayList();
|
||||
public List<SourceFile> parse(List<String> argsList) {
|
||||
List<SourceFile> srcs = new ArrayList<SourceFile>();
|
||||
ListIterator<String> args = argsList.listIterator();
|
||||
while (args.hasNext()) {
|
||||
String arg = (String)args.next();
|
||||
String arg = args.next();
|
||||
if (arg.equals("--")) {
|
||||
// "--" Stops command line processing
|
||||
break;
|
||||
|
@ -245,9 +241,7 @@ class Options {
|
|||
noDefaultLibs = true;
|
||||
}
|
||||
else if (arg.startsWith("-Wl,")) {
|
||||
Iterator opts = parseCommaSeparatedOptions(arg).iterator();
|
||||
while (opts.hasNext()) {
|
||||
String opt = (String)opts.next();
|
||||
for (String opt : parseCommaSeparatedOptions(arg)) {
|
||||
ldArgs.add(new LdOption(opt));
|
||||
}
|
||||
}
|
||||
|
@ -277,8 +271,7 @@ class Options {
|
|||
}
|
||||
// args has more arguments when "--" is appeared.
|
||||
while (args.hasNext()) {
|
||||
String arg = (String)args.next();
|
||||
addSourceFile(srcs, ldArgs, arg);
|
||||
addSourceFile(srcs, ldArgs, args.next());
|
||||
}
|
||||
if (srcs.isEmpty()) parseError("no input file");
|
||||
if (mode == null) {
|
||||
|
@ -294,14 +287,14 @@ class Options {
|
|||
throw new OptionParseError(msg);
|
||||
}
|
||||
|
||||
protected void addSourceFile(List srcs, List ldArgs, String sourceName) {
|
||||
protected void addSourceFile(List<SourceFile> srcs, List<LdArg> ldArgs, String sourceName) {
|
||||
SourceFile src = new SourceFile(sourceName);
|
||||
srcs.add(src);
|
||||
// Original argument order does matter when linking.
|
||||
ldArgs.add(src);
|
||||
}
|
||||
|
||||
protected String getOptArg(String opt, ListIterator args) {
|
||||
protected String getOptArg(String opt, ListIterator<String> args) {
|
||||
String path = opt.substring(2);
|
||||
if (path.length() != 0) { // -Ipath
|
||||
return path;
|
||||
|
@ -311,16 +304,16 @@ class Options {
|
|||
}
|
||||
}
|
||||
|
||||
protected String nextArg(String opt, ListIterator args) {
|
||||
protected String nextArg(String opt, ListIterator<String> args) {
|
||||
if (! args.hasNext()) {
|
||||
parseError("missing argument for " + opt);
|
||||
}
|
||||
return (String)args.next();
|
||||
return args.next();
|
||||
}
|
||||
|
||||
/** "-Wl,-rpath,/usr/local/lib" -> ["-rpath", "/usr/local/lib"] */
|
||||
protected List parseCommaSeparatedOptions(String opt) {
|
||||
List opts = arrayToList(opt.split(","));
|
||||
protected List<String> parseCommaSeparatedOptions(String opt) {
|
||||
List<String> opts = Arrays.asList(opt.split(","));
|
||||
opts.remove(0); // remove "-Wl" etc.
|
||||
if (opts.isEmpty()) {
|
||||
parseError("missing argument for " + opt);
|
||||
|
@ -328,14 +321,6 @@ class Options {
|
|||
return opts;
|
||||
}
|
||||
|
||||
protected List arrayToList(Object[] ary) {
|
||||
List result = new ArrayList();
|
||||
for (int i = 0; i < ary.length; i++) {
|
||||
result.add(ary[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public void printUsage(PrintStream out) {
|
||||
out.println("Usage: cbc [options] file...");
|
||||
out.println("Global Options:");
|
||||
|
|
|
@ -21,14 +21,10 @@ class TypeChecker extends Visitor {
|
|||
// #@@range/check_AST{
|
||||
public void check(AST ast) throws SemanticException {
|
||||
this.typeTable = ast.typeTable();
|
||||
Iterator vars = ast.variables();
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
for (DefinedVariable var : ast.definedVariables()) {
|
||||
checkVariable(var);
|
||||
}
|
||||
Iterator funcs = ast.functions();
|
||||
while (funcs.hasNext()) {
|
||||
DefinedFunction f = (DefinedFunction)funcs.next();
|
||||
for (DefinedFunction f : ast.definedFunctions()) {
|
||||
checkReturnType(f);
|
||||
checkParamTypes(f);
|
||||
check(f.body());
|
||||
|
@ -42,14 +38,11 @@ class TypeChecker extends Visitor {
|
|||
protected void checkReturnType(DefinedFunction f) {
|
||||
if (isInvalidReturnType(f.returnType())) {
|
||||
error(f, "returns invalid type: " + f.returnType());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkParamTypes(DefinedFunction f) {
|
||||
Iterator params = f.parameters();
|
||||
while (params.hasNext()) {
|
||||
Parameter param = (Parameter)params.next();
|
||||
for (Parameter param : f.parameters()) {
|
||||
if (isInvalidParameterType(param.type())) {
|
||||
error(param, "invalid parameter type: " + param.type());
|
||||
}
|
||||
|
@ -61,14 +54,10 @@ class TypeChecker extends Visitor {
|
|||
//
|
||||
|
||||
public void visit(BlockNode node) {
|
||||
Iterator vars = node.variables();
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
for (DefinedVariable var : node.variables()) {
|
||||
checkVariable(var);
|
||||
}
|
||||
Iterator stmts = node.stmts();
|
||||
while (stmts.hasNext()) {
|
||||
Node n = (Node)stmts.next();
|
||||
for (Node n : node.stmts()) {
|
||||
if (n instanceof ExprNode) {
|
||||
ExprNode expr = (ExprNode)n;
|
||||
if (isInvalidStatementType(expr.type())) {
|
||||
|
@ -468,17 +457,14 @@ class TypeChecker extends Visitor {
|
|||
return;
|
||||
}
|
||||
// Check type of only mandatory parameters.
|
||||
Iterator params = type.paramTypes();
|
||||
Iterator args = node.arguments();
|
||||
List newArgs = new ArrayList();
|
||||
while (params.hasNext()) {
|
||||
Type param = (Type)params.next();
|
||||
ExprNode arg = (ExprNode)args.next();
|
||||
Iterator<ExprNode> args = node.arguments().iterator();
|
||||
List<ExprNode> newArgs = new ArrayList<ExprNode>();
|
||||
for (Type param : type.paramTypes()) {
|
||||
ExprNode arg = args.next();
|
||||
newArgs.add(checkRHS(arg) ? implicitCast(param, arg) : arg);
|
||||
}
|
||||
while (args.hasNext()) {
|
||||
ExprNode arg = (ExprNode)args.next();
|
||||
newArgs.add(arg);
|
||||
newArgs.add(args.next());
|
||||
}
|
||||
node.replaceArgs(newArgs);
|
||||
}
|
||||
|
|
|
@ -25,15 +25,14 @@ public class TypeResolver extends Visitor {
|
|||
// #@@}
|
||||
|
||||
// #@@range/resolveNodeList{
|
||||
protected void resolveNodeList(Iterator nodes) {
|
||||
protected void resolveNodeList(List<? extends Node> nodes) {
|
||||
visitNodeList(nodes);
|
||||
}
|
||||
// #@@}
|
||||
|
||||
// #@@range/defineTypes{
|
||||
private void defineTypes(Iterator deftypes) {
|
||||
while (deftypes.hasNext()) {
|
||||
TypeDefinition def = (TypeDefinition)deftypes.next();
|
||||
private void defineTypes(List<TypeDefinition> deftypes) {
|
||||
for (TypeDefinition def : deftypes) {
|
||||
if (typeTable.isDefined(def.typeRef())) {
|
||||
error(def, "duplicated type definition: " + def.typeRef());
|
||||
}
|
||||
|
@ -69,10 +68,8 @@ public class TypeResolver extends Visitor {
|
|||
if (ct == null) {
|
||||
throw new Error("cannot intern struct/union: " + def.name());
|
||||
}
|
||||
Iterator membs = ct.members();
|
||||
while (membs.hasNext()) {
|
||||
Slot slot = (Slot)membs.next();
|
||||
bindType(slot.typeNode());
|
||||
for (Slot s : ct.members()) {
|
||||
bindType(s.typeNode());
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
@ -109,9 +106,7 @@ public class TypeResolver extends Visitor {
|
|||
// #@@range/resolveFunctionHeader{
|
||||
protected void resolveFunctionHeader(Function func) {
|
||||
bindType(func.typeNode());
|
||||
Iterator params = func.parameters();
|
||||
while (params.hasNext()) {
|
||||
Parameter param = (Parameter)params.next();
|
||||
for (Parameter param : func.parameters()) {
|
||||
bindType(param.typeNode());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,9 +10,8 @@ abstract public class Visitor implements ASTVisitor {
|
|||
node.accept(this);
|
||||
}
|
||||
|
||||
protected void visitNodeList(Iterator ns) {
|
||||
while (ns.hasNext()) {
|
||||
Node n = (Node)ns.next();
|
||||
protected void visitNodeList(List<? extends Node> nodes) {
|
||||
for (Node n : nodes) {
|
||||
visitNode(n);
|
||||
}
|
||||
}
|
||||
|
@ -50,9 +49,7 @@ abstract public class Visitor implements ASTVisitor {
|
|||
//
|
||||
|
||||
public void visit(BlockNode node) {
|
||||
Iterator vars = node.variables();
|
||||
while (vars.hasNext()) {
|
||||
DefinedVariable var = (DefinedVariable)vars.next();
|
||||
for (DefinedVariable var : node.variables()) {
|
||||
visit(var);
|
||||
}
|
||||
visitNodeList(node.stmts());
|
||||
|
|
|
@ -76,7 +76,7 @@ public class Parser {
|
|||
protected LibraryLoader loader;
|
||||
protected ErrorHandler errorHandler;
|
||||
protected LabelPool labelPool;
|
||||
protected Set knownTypedefs;
|
||||
protected Set<String> knownTypedefs;
|
||||
// #@@}
|
||||
|
||||
// #@@range/ctor1{
|
||||
|
@ -94,7 +94,7 @@ public class Parser {
|
|||
this.loader = loader;
|
||||
this.errorHandler = errorHandler;
|
||||
this.labelPool = new LabelPool();
|
||||
this.knownTypedefs = new HashSet();
|
||||
this.knownTypedefs = new HashSet<String>();
|
||||
if (debug) {
|
||||
enable_tracing();
|
||||
}
|
||||
|
@ -133,9 +133,8 @@ public class Parser {
|
|||
}
|
||||
}
|
||||
|
||||
private void addKnownTypedefs(Iterator typedefs) {
|
||||
while (typedefs.hasNext()) {
|
||||
TypedefNode n = (TypedefNode)typedefs.next();
|
||||
private void addKnownTypedefs(List<TypedefNode> typedefs) {
|
||||
for (TypedefNode n : typedefs) {
|
||||
addType(n.name());
|
||||
}
|
||||
}
|
||||
|
@ -429,7 +428,7 @@ Declarations import_stmts():
|
|||
Declarations decls = loader.loadLibrary(libid, errorHandler);
|
||||
if (decls != null) {
|
||||
impdecls.add(decls);
|
||||
addKnownTypedefs(decls.typedefs().iterator());
|
||||
addKnownTypedefs(decls.typedefs());
|
||||
}
|
||||
}
|
||||
catch (CompileException ex) {
|
||||
|
@ -464,7 +463,7 @@ Declarations top_defs():
|
|||
{
|
||||
Declarations decls = new Declarations();
|
||||
DefinedFunction defun;
|
||||
List defvars;
|
||||
List<DefinedVariable> defvars;
|
||||
StructNode defstruct;
|
||||
UnionNode defunion;
|
||||
TypedefNode typedef;
|
||||
|
@ -485,9 +484,9 @@ Declarations top_defs():
|
|||
// #@@}
|
||||
|
||||
// #@@range/defvars{
|
||||
List defvars():
|
||||
List<DefinedVariable> defvars():
|
||||
{
|
||||
List defs = new ArrayList();
|
||||
List<DefinedVariable> defs = new ArrayList<DefinedVariable>();
|
||||
boolean priv;
|
||||
TypeNode type;
|
||||
String name;
|
||||
|
@ -523,9 +522,9 @@ DefinedFunction defun():
|
|||
{
|
||||
priv=storage() ref=typeref() n=name() "(" ps=params() ")" body=block()
|
||||
{
|
||||
Params ptypes = ps.typeRefs();
|
||||
ParamTypeRefs paramref = ps.parametersTypeRef();
|
||||
TypeNode t = new TypeNode(new PointerTypeRef(
|
||||
new FunctionTypeRef(ref, ptypes)));
|
||||
new FunctionTypeRef(ref, paramref)));
|
||||
return new DefinedFunction(labelPool, priv, t, n, ps, body);
|
||||
}
|
||||
}
|
||||
|
@ -543,16 +542,16 @@ boolean storage():
|
|||
Params params():
|
||||
{
|
||||
Token t;
|
||||
FixedParams params;
|
||||
Params params;
|
||||
}
|
||||
{
|
||||
LOOKAHEAD(<VOID> ")")
|
||||
t=<VOID>
|
||||
{
|
||||
return new FixedParams(location(t), new ArrayList());
|
||||
return new Params(location(t), new ArrayList<Parameter>());
|
||||
}
|
||||
| params=fixedparams()
|
||||
["," "..." { return new VarParams(params); }]
|
||||
["," "..." { params.acceptVarargs(); }]
|
||||
{
|
||||
return params;
|
||||
}
|
||||
|
@ -560,16 +559,16 @@ Params params():
|
|||
// #@@}
|
||||
|
||||
// #@@range/fixedparams{
|
||||
FixedParams fixedparams():
|
||||
Params fixedparams():
|
||||
{
|
||||
List params = new ArrayList();
|
||||
List<Parameter> params = new ArrayList<Parameter>();
|
||||
Parameter param, param1;
|
||||
}
|
||||
{
|
||||
param1=param() { params.add(param1); }
|
||||
( LOOKAHEAD(2) "," param=param() { params.add(param); } )*
|
||||
{
|
||||
return new FixedParams(param1.location(), params);
|
||||
return new Params(param1.location(), params);
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
@ -589,8 +588,8 @@ Parameter param():
|
|||
BlockNode block():
|
||||
{
|
||||
Token t;
|
||||
List vars;
|
||||
List stmts;
|
||||
List<DefinedVariable> vars;
|
||||
List<Node> stmts;
|
||||
}
|
||||
{
|
||||
t="{" vars=defvar_list() stmts=stmts() "}"
|
||||
|
@ -602,10 +601,10 @@ BlockNode block():
|
|||
|
||||
|
||||
// #@@range/defvar_list{
|
||||
List defvar_list():
|
||||
List<DefinedVariable> defvar_list():
|
||||
{
|
||||
List result = new ArrayList();
|
||||
List vars;
|
||||
List<DefinedVariable> result = new ArrayList<DefinedVariable>();
|
||||
List<DefinedVariable> vars;
|
||||
}
|
||||
{
|
||||
( vars=defvars() { result.addAll(vars); } )*
|
||||
|
@ -620,7 +619,7 @@ StructNode defstruct():
|
|||
{
|
||||
Token t;
|
||||
String n;
|
||||
List membs;
|
||||
List<Slot> membs;
|
||||
}
|
||||
{
|
||||
t=<STRUCT> n=name() membs=member_list() ";"
|
||||
|
@ -634,7 +633,7 @@ UnionNode defunion():
|
|||
{
|
||||
Token t;
|
||||
String n;
|
||||
List membs;
|
||||
List<Slot> membs;
|
||||
}
|
||||
{
|
||||
t=<UNION> n=name() membs=member_list() ";"
|
||||
|
@ -644,9 +643,9 @@ UnionNode defunion():
|
|||
}
|
||||
|
||||
// #@@range/member_list{
|
||||
List member_list():
|
||||
List<Slot> member_list():
|
||||
{
|
||||
List membs = new ArrayList();
|
||||
List<Slot> membs = new ArrayList<Slot>();
|
||||
Slot s;
|
||||
}
|
||||
{
|
||||
|
@ -678,9 +677,9 @@ UndefinedFunction funcdecl():
|
|||
{
|
||||
<EXTERN> ref=typeref() n=name() "(" ps=params() ")" ";"
|
||||
{
|
||||
Params ptyperefs = ps.typeRefs();
|
||||
ParamTypeRefs paramref = ps.parametersTypeRef();
|
||||
TypeNode t = new TypeNode(new PointerTypeRef(
|
||||
new FunctionTypeRef(ref, ptyperefs)));
|
||||
new FunctionTypeRef(ref, paramref)));
|
||||
return new UndefinedFunction(t, n, ps);
|
||||
}
|
||||
}
|
||||
|
@ -711,7 +710,7 @@ TypeRef typeref():
|
|||
{
|
||||
TypeRef ref;
|
||||
Token t;
|
||||
Params params;
|
||||
ParamTypeRefs params;
|
||||
}
|
||||
{
|
||||
ref=typeref_base()
|
||||
|
@ -740,16 +739,16 @@ TypeRef typeref():
|
|||
// #@@}
|
||||
|
||||
// #@@range/param_typerefs{
|
||||
Params param_typerefs():
|
||||
{ FixedParams params; }
|
||||
ParamTypeRefs param_typerefs():
|
||||
{ ParamTypeRefs params; }
|
||||
{
|
||||
LOOKAHEAD(<VOID> ")")
|
||||
<VOID>
|
||||
{
|
||||
return new FixedParams(new ArrayList());
|
||||
return new ParamTypeRefs(new ArrayList<TypeRef>());
|
||||
}
|
||||
| params=fixedparam_typerefs()
|
||||
[ "," "..." { return new VarParams(params); } ]
|
||||
[ "," "..." { params.acceptVarargs(); }]
|
||||
{
|
||||
return params;
|
||||
}
|
||||
|
@ -757,16 +756,16 @@ Params param_typerefs():
|
|||
// #@@}
|
||||
|
||||
// #@@range/fixedparam_typerefs{
|
||||
FixedParams fixedparam_typerefs():
|
||||
ParamTypeRefs fixedparam_typerefs():
|
||||
{
|
||||
List refs = new ArrayList();
|
||||
List<TypeRef> refs = new ArrayList<TypeRef>();
|
||||
TypeRef ref;
|
||||
}
|
||||
{
|
||||
ref=typeref() { refs.add(ref); }
|
||||
( LOOKAHEAD(2) "," ref=typeref() { refs.add(ref); } )*
|
||||
{
|
||||
return new FixedParams(refs);
|
||||
return new ParamTypeRefs(refs);
|
||||
}
|
||||
}
|
||||
// #@@}
|
||||
|
@ -816,9 +815,9 @@ TypedefNode typedef():
|
|||
// #@@}
|
||||
|
||||
// #@@range/stmts{
|
||||
List stmts():
|
||||
List<Node> stmts():
|
||||
{
|
||||
List ss = new ArrayList();
|
||||
List<Node> ss = new ArrayList<Node>();
|
||||
Node s;
|
||||
}
|
||||
{
|
||||
|
@ -928,7 +927,7 @@ SwitchNode switch_stmt():
|
|||
{
|
||||
Token t;
|
||||
ExprNode cond;
|
||||
List bodies;
|
||||
List<CaseNode> bodies;
|
||||
}
|
||||
{
|
||||
t=<SWITCH> "(" cond=expr() ")" "{" bodies=case_clauses() "}"
|
||||
|
@ -937,10 +936,10 @@ SwitchNode switch_stmt():
|
|||
}
|
||||
}
|
||||
|
||||
List case_clauses():
|
||||
List<CaseNode> case_clauses():
|
||||
{
|
||||
List clauses = new ArrayList();
|
||||
Node n;
|
||||
List<CaseNode> clauses = new ArrayList<CaseNode>();
|
||||
CaseNode n;
|
||||
}
|
||||
{
|
||||
(n=case_clause() { clauses.add(n); })*
|
||||
|
@ -952,7 +951,7 @@ List case_clauses():
|
|||
|
||||
CaseNode case_clause():
|
||||
{
|
||||
List values;
|
||||
List<ExprNode> values;
|
||||
BlockNode body;
|
||||
}
|
||||
{
|
||||
|
@ -962,9 +961,9 @@ CaseNode case_clause():
|
|||
}
|
||||
}
|
||||
|
||||
List cases():
|
||||
List<ExprNode> cases():
|
||||
{
|
||||
List values = new ArrayList();
|
||||
List<ExprNode> values = new ArrayList<ExprNode>();
|
||||
ExprNode n;
|
||||
}
|
||||
{
|
||||
|
@ -980,25 +979,26 @@ CaseNode default_clause():
|
|||
<DEFAULT_> ":" body=case_body()
|
||||
{
|
||||
return new CaseNode(body.location(), labelPool,
|
||||
new ArrayList(), body);
|
||||
new ArrayList<ExprNode>(), body);
|
||||
}
|
||||
}
|
||||
|
||||
BlockNode case_body():
|
||||
{
|
||||
LinkedList ss = new LinkedList();
|
||||
LinkedList<Node> stmts = new LinkedList<Node>();
|
||||
Node s;
|
||||
}
|
||||
{
|
||||
(s=stmt() { if (s != null) ss.add(s); })+
|
||||
(s=stmt() { if (s != null) stmts.add(s); })+
|
||||
{
|
||||
// last stmt of case clause must be break stmt.
|
||||
if (! (ss.getLast() instanceof BreakNode)) {
|
||||
if (! (stmts.getLast() instanceof BreakNode)) {
|
||||
throw new ParseException(
|
||||
"missing break statement at the last of case clause");
|
||||
}
|
||||
return new BlockNode(((Node)ss.get(0)).location(),
|
||||
new ArrayList(), ss);
|
||||
return new BlockNode(stmts.get(0).location(),
|
||||
new ArrayList<DefinedVariable>(),
|
||||
stmts);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1244,7 +1244,7 @@ ExprNode postfix():
|
|||
{
|
||||
ExprNode expr, idx;
|
||||
String memb;
|
||||
List args;
|
||||
List<ExprNode> args;
|
||||
}
|
||||
{
|
||||
expr=primary()
|
||||
|
@ -1270,9 +1270,9 @@ String name():
|
|||
// #@@}
|
||||
|
||||
// #@@range/args{
|
||||
List args():
|
||||
List<ExprNode> args():
|
||||
{
|
||||
List args = new ArrayList();
|
||||
List<ExprNode> args = new ArrayList<ExprNode>();
|
||||
ExprNode arg;
|
||||
}
|
||||
{
|
||||
|
|
|
@ -6,12 +6,12 @@ import java.util.*;
|
|||
import java.lang.reflect.*;
|
||||
|
||||
abstract public class CompositeType extends NamedType {
|
||||
protected List members; // List<Slot>
|
||||
protected List<Slot> members;
|
||||
protected long cachedSize;
|
||||
protected long cachedAlign;
|
||||
protected boolean isRecursiveChecked;
|
||||
|
||||
public CompositeType(String name, List membs, Location loc) {
|
||||
public CompositeType(String name, List<Slot> membs, Location loc) {
|
||||
super(name, loc);
|
||||
this.members = membs;
|
||||
this.cachedSize = Type.sizeUnknown;
|
||||
|
@ -40,12 +40,9 @@ abstract public class CompositeType extends NamedType {
|
|||
if (isUnion() && !other.isUnion()) return false;
|
||||
CompositeType otherType = other.getCompositeType();
|
||||
if (members.size() != other.size()) return false;
|
||||
Iterator types = memberTypes();
|
||||
Iterator otherTypes = otherType.memberTypes();
|
||||
while (types.hasNext()) {
|
||||
if (! compareTypesBy(cmpMethod,
|
||||
(Type)types.next(),
|
||||
(Type)otherTypes.next())) {
|
||||
Iterator<Type> otherTypes = otherType.memberTypes().iterator();
|
||||
for (Type t : memberTypes()) {
|
||||
if (! compareTypesBy(cmpMethod, t, otherTypes.next())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -84,19 +81,16 @@ abstract public class CompositeType extends NamedType {
|
|||
return cachedAlign;
|
||||
}
|
||||
|
||||
/** Returns a List<Slot> of members. */
|
||||
public Iterator members() {
|
||||
return members.iterator();
|
||||
public List<Slot> members() {
|
||||
return members;
|
||||
}
|
||||
|
||||
/** Returns a List<Type> of members. */
|
||||
public Iterator memberTypes() {
|
||||
Iterator membs = members.iterator();
|
||||
List result = new ArrayList();
|
||||
while (membs.hasNext()) {
|
||||
result.add(((Slot)membs.next()).type());
|
||||
public List<Type> memberTypes() {
|
||||
List<Type> result = new ArrayList<Type>();
|
||||
for (Slot s : members) {
|
||||
result.add(s.type());
|
||||
}
|
||||
return result.iterator();
|
||||
return result;
|
||||
}
|
||||
|
||||
public boolean hasMember(String name) {
|
||||
|
@ -127,9 +121,7 @@ abstract public class CompositeType extends NamedType {
|
|||
}
|
||||
|
||||
public Slot get(String name) {
|
||||
Iterator membs = members.iterator();
|
||||
while (membs.hasNext()) {
|
||||
Slot s = (Slot)membs.next();
|
||||
for (Slot s : members) {
|
||||
if (s.name().equals(name)) {
|
||||
return s;
|
||||
}
|
||||
|
|
|
@ -4,9 +4,9 @@ import java.util.*;
|
|||
|
||||
public class FunctionType extends Type {
|
||||
protected Type returnType;
|
||||
protected Params paramTypes;
|
||||
protected ParamTypes paramTypes;
|
||||
|
||||
public FunctionType(Type ret, Params partypes) {
|
||||
public FunctionType(Type ret, ParamTypes partypes) {
|
||||
returnType = ret;
|
||||
paramTypes = partypes;
|
||||
}
|
||||
|
@ -52,8 +52,8 @@ public class FunctionType extends Type {
|
|||
* Returns iterator of mandatory parameter types.
|
||||
* This method does NOT include types for varargs.
|
||||
*/
|
||||
public Iterator paramTypes() {
|
||||
return paramTypes.parameters();
|
||||
public List<Type> paramTypes() {
|
||||
return paramTypes.types();
|
||||
}
|
||||
|
||||
public long alignment() {
|
||||
|
@ -68,9 +68,7 @@ public class FunctionType extends Type {
|
|||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(returnType.toString());
|
||||
buf.append(" (*)(");
|
||||
Iterator params = paramTypes.parameters();
|
||||
while (params.hasNext()) {
|
||||
Type t = (Type)params.next();
|
||||
for (Type t : paramTypes.types()) {
|
||||
buf.append(t.toString());
|
||||
}
|
||||
buf.append(")");
|
||||
|
|
|
@ -4,9 +4,9 @@ import java.util.*;
|
|||
|
||||
public class FunctionTypeRef extends TypeRef {
|
||||
protected TypeRef returnType;
|
||||
protected Params params;
|
||||
protected ParamTypeRefs params;
|
||||
|
||||
public FunctionTypeRef(TypeRef returnType, Params params) {
|
||||
public FunctionTypeRef(TypeRef returnType, ParamTypeRefs params) {
|
||||
super(returnType.location());
|
||||
this.returnType = returnType;
|
||||
this.params = params;
|
||||
|
@ -17,17 +17,20 @@ public class FunctionTypeRef extends TypeRef {
|
|||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
if (!(other instanceof FunctionTypeRef)) return false;
|
||||
FunctionTypeRef ref = (FunctionTypeRef)other;
|
||||
return returnType.equals(ref.returnType()) &&
|
||||
params.equals(ref.params());
|
||||
return (other instanceof FunctionTypeRef)
|
||||
&& equals((FunctionTypeRef)other);
|
||||
}
|
||||
|
||||
public boolean equals(FunctionTypeRef other) {
|
||||
return returnType.equals(other.returnType())
|
||||
&& params.equals(other.params());
|
||||
}
|
||||
|
||||
public TypeRef returnType() {
|
||||
return returnType;
|
||||
}
|
||||
|
||||
public Params params() {
|
||||
public ParamTypeRefs params() {
|
||||
return params;
|
||||
}
|
||||
|
||||
|
@ -35,10 +38,8 @@ public class FunctionTypeRef extends TypeRef {
|
|||
StringBuffer buf = new StringBuffer();
|
||||
buf.append(returnType.toString());
|
||||
buf.append(" (");
|
||||
Iterator params = this.params.parameters();
|
||||
String sep = "";
|
||||
while (params.hasNext()) {
|
||||
TypeRef ref = (TypeRef)params.next();
|
||||
for (TypeRef ref : this.params.typerefs()) {
|
||||
buf.append(sep);
|
||||
buf.append(ref.toString());
|
||||
sep = ", ";
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
package net.loveruby.cflat.type;
|
||||
import net.loveruby.cflat.ast.ParamSlots;
|
||||
import net.loveruby.cflat.ast.Location;
|
||||
import java.util.*;
|
||||
|
||||
public class ParamTypeRefs extends ParamSlots<TypeRef> {
|
||||
public ParamTypeRefs(List<TypeRef> paramDescs) {
|
||||
super(paramDescs);
|
||||
}
|
||||
|
||||
public ParamTypeRefs(Location loc, List<TypeRef> paramDescs, boolean vararg) {
|
||||
super(loc, paramDescs, vararg);
|
||||
}
|
||||
|
||||
public List<TypeRef> typerefs() {
|
||||
return paramDescriptors;
|
||||
}
|
||||
|
||||
public ParamTypes internTypes(TypeTable table) {
|
||||
List<Type> types = new ArrayList<Type>();
|
||||
for (TypeRef ref : paramDescriptors) {
|
||||
types.add(table.get(ref));
|
||||
}
|
||||
return new ParamTypes(location, types, vararg);
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
return (other instanceof ParamTypeRefs)
|
||||
&& equals((ParamTypeRefs)other);
|
||||
}
|
||||
|
||||
public boolean equals(ParamTypeRefs other) {
|
||||
return vararg == other.vararg
|
||||
&& paramDescriptors.equals(other.paramDescriptors);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package net.loveruby.cflat.type;
|
||||
import net.loveruby.cflat.ast.ParamSlots;
|
||||
import net.loveruby.cflat.ast.Location;
|
||||
import java.util.*;
|
||||
|
||||
public class ParamTypes extends ParamSlots<Type> {
|
||||
protected ParamTypes(Location loc, List<Type> paramDescs, boolean vararg) {
|
||||
super(loc, paramDescs, vararg);
|
||||
}
|
||||
|
||||
public List<Type> types() {
|
||||
return paramDescriptors;
|
||||
}
|
||||
|
||||
public boolean isSameType(ParamTypes other) {
|
||||
if (vararg != other.vararg) return false;
|
||||
if (minArgc() != other.minArgc()) return false;
|
||||
Iterator<Type> otherTypes = other.types().iterator();
|
||||
for (Type t : paramDescriptors) {
|
||||
if (! t.isSameType(otherTypes.next())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean equals(Object other) {
|
||||
return (other instanceof ParamTypes) && equals((ParamTypes)other);
|
||||
}
|
||||
|
||||
public boolean equals(ParamTypes other) {
|
||||
return vararg == other.vararg
|
||||
&& paramDescriptors.equals(other.paramDescriptors);
|
||||
}
|
||||
}
|
|
@ -5,7 +5,7 @@ import net.loveruby.cflat.asm.Assembler;
|
|||
import java.util.*;
|
||||
|
||||
public class StructType extends CompositeType {
|
||||
public StructType(String name, List membs, Location loc) {
|
||||
public StructType(String name, List<Slot> membs, Location loc) {
|
||||
super(name, membs, loc);
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,7 @@ public class StructType extends CompositeType {
|
|||
protected void computeOffsets() {
|
||||
long offset = 0;
|
||||
long maxAlign = 1;
|
||||
Iterator membs = members();
|
||||
while (membs.hasNext()) {
|
||||
Slot s = (Slot)membs.next();
|
||||
for (Slot s : members()) {
|
||||
offset = Assembler.align(offset, s.allocSize());
|
||||
s.setOffset(offset);
|
||||
offset += s.allocSize();
|
||||
|
|
|
@ -34,11 +34,11 @@ public class TypeTable {
|
|||
}
|
||||
|
||||
protected int pointerSize;
|
||||
protected Map table;
|
||||
protected Map<TypeRef, Type> table;
|
||||
|
||||
public TypeTable(int ptrsize) {
|
||||
pointerSize = ptrsize;
|
||||
table = new HashMap();
|
||||
table = new HashMap<TypeRef, Type>();
|
||||
}
|
||||
|
||||
public boolean isDefined(TypeRef ref) {
|
||||
|
@ -53,7 +53,7 @@ public class TypeTable {
|
|||
}
|
||||
|
||||
public Type get(TypeRef ref) {
|
||||
Type type = (Type)table.get(ref);
|
||||
Type type = table.get(ref);
|
||||
if (type == null) {
|
||||
if (ref instanceof UserTypeRef) {
|
||||
// If unregistered UserType is used in program, it causes
|
||||
|
@ -104,8 +104,8 @@ public class TypeTable {
|
|||
throw new Error("must not happen: integer.size != pointer.size");
|
||||
}
|
||||
|
||||
public Iterator types() {
|
||||
return table.values().iterator();
|
||||
public Collection<Type> types() {
|
||||
return table.values();
|
||||
}
|
||||
|
||||
public VoidType voidType() {
|
||||
|
@ -149,12 +149,10 @@ public class TypeTable {
|
|||
}
|
||||
|
||||
public void semanticCheck(ErrorHandler h) {
|
||||
Iterator types = table.values().iterator();
|
||||
while (types.hasNext()) {
|
||||
// We can safely use instanceof instead of isXXXX() here,
|
||||
for (Type t : types()) {
|
||||
// We can safely use "instanceof" instead of isXXXX() here,
|
||||
// because the type refered from UserType must be also
|
||||
// kept in this table.
|
||||
Type t = (Type)types.next();
|
||||
if (t instanceof CompositeType) {
|
||||
checkVoidMembers((CompositeType)t, h);
|
||||
checkDuplicatedMembers((CompositeType)t, h);
|
||||
|
@ -173,38 +171,34 @@ public class TypeTable {
|
|||
}
|
||||
|
||||
protected void checkVoidMembers(CompositeType t, ErrorHandler h) {
|
||||
Iterator membs = t.members();
|
||||
while (membs.hasNext()) {
|
||||
Slot memb = (Slot)membs.next();
|
||||
if (memb.type().isVoid()) {
|
||||
for (Slot s : t.members()) {
|
||||
if (s.type().isVoid()) {
|
||||
h.error(t.location(), "struct/union cannot contain void");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void checkDuplicatedMembers(CompositeType t, ErrorHandler h) {
|
||||
Map seen = new HashMap();
|
||||
Iterator membs = t.members();
|
||||
while (membs.hasNext()) {
|
||||
Slot memb = (Slot)membs.next();
|
||||
if (seen.containsKey(memb.name())) {
|
||||
Map<String, Slot> seen = new HashMap<String, Slot>();
|
||||
for (Slot s : t.members()) {
|
||||
if (seen.containsKey(s.name())) {
|
||||
h.error(t.location(),
|
||||
t.toString() + " has duplicated member: "
|
||||
+ memb.name());
|
||||
t.toString() + " has duplicated member: " + s.name());
|
||||
}
|
||||
seen.put(memb.name(), memb);
|
||||
seen.put(s.name(), s);
|
||||
}
|
||||
}
|
||||
|
||||
// #@@range/checkRecursiveDefinition{
|
||||
protected void checkRecursiveDefinition(Type t, ErrorHandler h) {
|
||||
_checkRecursiveDefinition(t, new HashMap(), h);
|
||||
_checkRecursiveDefinition(t, new HashMap<Type, Object>(), h);
|
||||
}
|
||||
|
||||
static final protected Object checking = new Object();
|
||||
static final protected Object checked = new Object();
|
||||
|
||||
protected void _checkRecursiveDefinition(Type t, Map marks,
|
||||
protected void _checkRecursiveDefinition(Type t,
|
||||
Map<Type, Object> marks,
|
||||
ErrorHandler h) {
|
||||
if (marks.get(t) == checking) {
|
||||
h.error(((NamedType)t).location(),
|
||||
|
@ -218,10 +212,8 @@ public class TypeTable {
|
|||
marks.put(t, checking);
|
||||
if (t instanceof CompositeType) {
|
||||
CompositeType ct = (CompositeType)t;
|
||||
Iterator membs = ct.members();
|
||||
while (membs.hasNext()) {
|
||||
Slot slot = (Slot)membs.next();
|
||||
_checkRecursiveDefinition(slot.type(), marks, h);
|
||||
for (Slot s : ct.members()) {
|
||||
_checkRecursiveDefinition(s.type(), marks, h);
|
||||
}
|
||||
}
|
||||
else if (t instanceof ArrayType) {
|
||||
|
|
|
@ -5,7 +5,7 @@ import net.loveruby.cflat.asm.Assembler;
|
|||
import java.util.*;
|
||||
|
||||
public class UnionType extends CompositeType {
|
||||
public UnionType(String name, List membs, Location loc) {
|
||||
public UnionType(String name, List<Slot> membs, Location loc) {
|
||||
super(name, membs, loc);
|
||||
}
|
||||
|
||||
|
@ -19,9 +19,7 @@ public class UnionType extends CompositeType {
|
|||
protected void computeOffsets() {
|
||||
long maxSize = 0;
|
||||
long maxAlign = 1;
|
||||
Iterator membs = members.iterator();
|
||||
while (membs.hasNext()) {
|
||||
Slot s = (Slot)membs.next();
|
||||
for (Slot s : members) {
|
||||
s.setOffset(0);
|
||||
maxSize = Math.max(maxSize, s.allocSize());
|
||||
maxAlign = Math.max(maxAlign, s.alignment());
|
||||
|
|
|
@ -1,36 +1,32 @@
|
|||
package net.loveruby.cflat.utils;
|
||||
import java.util.*;
|
||||
|
||||
public class Cursor implements Iterator {
|
||||
protected List list;
|
||||
public class Cursor<T> implements Iterator {
|
||||
protected List<T> list;
|
||||
protected int index;
|
||||
|
||||
public Cursor(List list) {
|
||||
public Cursor(List<T> list) {
|
||||
this(list, 0);
|
||||
}
|
||||
|
||||
protected Cursor(List list, int index) {
|
||||
protected Cursor(List<T> list, int index) {
|
||||
this.list = list;
|
||||
this.index = index;
|
||||
}
|
||||
|
||||
public Object clone() {
|
||||
return new Cursor(list, index);
|
||||
}
|
||||
|
||||
public Cursor dup() {
|
||||
return new Cursor(list, index);
|
||||
public Cursor<T> clone() {
|
||||
return new Cursor<T>(list, index);
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
return index < list.size();
|
||||
}
|
||||
|
||||
public Object next() {
|
||||
public T next() {
|
||||
return list.get(index++);
|
||||
}
|
||||
|
||||
public Object current() {
|
||||
public T current() {
|
||||
if (index == 0) {
|
||||
throw new Error("must not happen: Cursor#current");
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue