r4887@macbookpro: aamine | 2009-05-23 23:30:32 +0900

* net/loveruby/cflat/compiler/IRGenerator.java: refactoring: use reverse(node.args) instead of ListIterator.
 * net/loveruby/cflat/sysdep/x86/CodeGenerator.java: ditto.
 * net/loveruby/cflat/utils/ListUtils.java: new utility class.
 * net/loveruby/cflat/ast/FuncallNode.java: remove #finalArgs.
 * net/loveruby/cflat/ir/Call.java: ditto.
 * net/loveruby/cflat/ast/FuncallNode.java: refactoring: rename method: arguments -> args.
 * net/loveruby/cflat/compiler/Visitor.java: follow it.
 * net/loveruby/cflat/compiler/TypeChecker.java: ditto.
 


git-svn-id: file:///Users/aamine/c/gitwork/public/cbc/trunk@4232 1b9489fe-b721-0410-924e-b54b9192deb8
This commit is contained in:
Minero Aoki 2009-05-23 14:31:37 +00:00
parent e002c1089a
commit a54e95aa16
11 changed files with 101 additions and 45 deletions

View File

@ -1,3 +1,23 @@
Sat May 23 23:31:17 2009 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/compiler/IRGenerator.java: refactoring: use
reverse(node.args) instead of ListIterator.
* net/loveruby/cflat/sysdep/x86/CodeGenerator.java: ditto.
* net/loveruby/cflat/utils/ListUtils.java: new utility class.
* net/loveruby/cflat/ast/FuncallNode.java: remove #finalArgs.
* net/loveruby/cflat/ir/Call.java: ditto.
* net/loveruby/cflat/ast/FuncallNode.java: refactoring: rename
method: arguments -> args.
* net/loveruby/cflat/compiler/Visitor.java: follow it.
* net/loveruby/cflat/compiler/TypeChecker.java: ditto.
Sat May 23 22:31:06 2009 Minero Aoki <aamine@loveruby.net> Sat May 23 22:31:06 2009 Minero Aoki <aamine@loveruby.net>
* net/loveruby/cflat/parser/Parser.jj: now NULL is not a reserved * net/loveruby/cflat/parser/Parser.jj: now NULL is not a reserved

View File

@ -5,11 +5,11 @@ import java.util.*;
public class FuncallNode extends ExprNode { public class FuncallNode extends ExprNode {
protected ExprNode expr; protected ExprNode expr;
protected List<ExprNode> arguments; protected List<ExprNode> args;
public FuncallNode(ExprNode expr, List<ExprNode> arguments) { public FuncallNode(ExprNode expr, List<ExprNode> args) {
this.expr = expr; this.expr = expr;
this.arguments = arguments; this.args = args;
} }
public ExprNode expr() { public ExprNode expr() {
@ -38,20 +38,16 @@ public class FuncallNode extends ExprNode {
} }
public long numArgs() { public long numArgs() {
return arguments.size(); return args.size();
} }
public List<ExprNode> arguments() { public List<ExprNode> args() {
return arguments; return args;
} }
// called from TypeChecker // called from TypeChecker
public void replaceArgs(List<ExprNode> args) { public void replaceArgs(List<ExprNode> args) {
this.arguments = args; this.args = args;
}
public ListIterator<ExprNode> finalArg() {
return arguments.listIterator(arguments.size());
} }
public Location location() { public Location location() {
@ -60,7 +56,7 @@ public class FuncallNode extends ExprNode {
protected void _dump(Dumper d) { protected void _dump(Dumper d) {
d.printMember("expr", expr); d.printMember("expr", expr);
d.printNodeList("arguments", arguments); d.printNodeList("args", args);
} }
public <S,E> E accept(ASTVisitor<S,E> visitor) { public <S,E> E accept(ASTVisitor<S,E> visitor) {

View File

@ -6,6 +6,7 @@ import net.loveruby.cflat.type.TypeTable;
import net.loveruby.cflat.ir.*; import net.loveruby.cflat.ir.*;
import net.loveruby.cflat.asm.Label; import net.loveruby.cflat.asm.Label;
import net.loveruby.cflat.utils.ErrorHandler; import net.loveruby.cflat.utils.ErrorHandler;
import net.loveruby.cflat.utils.ListUtils;
import net.loveruby.cflat.exception.*; import net.loveruby.cflat.exception.*;
import java.util.*; import java.util.*;
@ -554,30 +555,25 @@ class IRGenerator implements ASTVisitor<Void, Expr> {
} }
// #@@} // #@@}
// #@@range/Funcall{
public Expr visit(FuncallNode node) { public Expr visit(FuncallNode node) {
List<Expr> newArgs = new ArrayList<Expr>(); List<Expr> args = new ArrayList<Expr>();
ListIterator<ExprNode> args = node.finalArg(); for (ExprNode arg : ListUtils.reverse(node.args())) {
while (args.hasPrevious()) { args.add(0, transformExpr(arg));
newArgs.add(0, transformExpr(args.previous()));
} }
Expr call = new Call(asmType(node.type()),
transformExpr(node.expr()), args);
if (isStatement()) { if (isStatement()) {
stmts.add( stmts.add(new ExprStmt(node.location(), call));
new ExprStmt(node.location(),
new Call(asmType(node.type()),
transformExpr(node.expr()),
newArgs)));
return null; return null;
} }
else { else {
DefinedVariable tmp = tmpVar(node.type()); DefinedVariable tmp = tmpVar(node.type());
assign(node.location(), assign(node.location(), ref(tmp), call);
ref(tmp),
new Call(asmType(node.type()),
transformExpr(node.expr()),
newArgs));
return ref(tmp); return ref(tmp);
} }
} }
// #@@}
// //
// Expressions (no side effects) // Expressions (no side effects)

View File

@ -460,7 +460,7 @@ class TypeChecker extends Visitor {
error(node, "wrong number of argments: " + node.numArgs()); error(node, "wrong number of argments: " + node.numArgs());
return null; return null;
} }
Iterator<ExprNode> args = node.arguments().iterator(); Iterator<ExprNode> args = node.args().iterator();
List<ExprNode> newArgs = new ArrayList<ExprNode>(); List<ExprNode> newArgs = new ArrayList<ExprNode>();
// mandatory args // mandatory args
for (Type param : type.paramTypes()) { for (Type param : type.paramTypes()) {

View File

@ -172,7 +172,7 @@ abstract public class Visitor implements ASTVisitor<Void, Void> {
public Void visit(FuncallNode node) { public Void visit(FuncallNode node) {
visitExpr(node.expr()); visitExpr(node.expr());
visitExprs(node.arguments()); visitExprs(node.args());
return null; return null;
} }

View File

@ -3,7 +3,6 @@ import net.loveruby.cflat.entity.Function;
import net.loveruby.cflat.entity.Entity; import net.loveruby.cflat.entity.Entity;
import net.loveruby.cflat.asm.Type; import net.loveruby.cflat.asm.Type;
import java.util.List; import java.util.List;
import java.util.ListIterator;
public class Call extends Expr { public class Call extends Expr {
private Expr expr; private Expr expr;
@ -16,16 +15,12 @@ public class Call extends Expr {
} }
public Expr expr() { return expr; } public Expr expr() { return expr; }
public List<Expr> arguments() { return args; } public List<Expr> args() { return args; }
public long numArgs() { public long numArgs() {
return args.size(); return args.size();
} }
public ListIterator<Expr> finalArg() {
return args.listIterator(args.size());
}
/** Returns true if this funcall is NOT a function pointer call. */ /** Returns true if this funcall is NOT a function pointer call. */
public boolean isStaticCall() { public boolean isStaticCall() {
return (expr.getEntityForce() instanceof Function); return (expr.getEntityForce() instanceof Function);

View File

@ -5,6 +5,7 @@ import net.loveruby.cflat.entity.*;
import net.loveruby.cflat.asm.*; import net.loveruby.cflat.asm.*;
import net.loveruby.cflat.ast.Location; import net.loveruby.cflat.ast.Location;
import net.loveruby.cflat.utils.AsmUtils; import net.loveruby.cflat.utils.AsmUtils;
import net.loveruby.cflat.utils.ListUtils;
import net.loveruby.cflat.utils.ErrorHandler; import net.loveruby.cflat.utils.ErrorHandler;
import java.util.*; import java.util.*;
@ -639,28 +640,22 @@ public class CodeGenerator
/** /**
* Implements cdecl function call: * Implements cdecl function call:
* * All arguments are on stack. * * All arguments are on stack.
* * Rewind stack by caller. * * Caller rewinds stack pointer.
*/ */
// #@@range/compile_Funcall{ // #@@range/compile_Funcall{
public Void visit(Call node) { public Void visit(Call node) {
// compile function arguments from right to left. for (Expr arg : ListUtils.reverse(node.args())) {
ListIterator<Expr> args = node.finalArg(); compile(arg);
while (args.hasPrevious()) {
compile(args.previous());
as.push(ax()); as.push(ax());
} }
// call
if (node.isStaticCall()) { if (node.isStaticCall()) {
// call via function name
as.call(node.function().callingSymbol()); as.call(node.function().callingSymbol());
} }
else { else {
// call via pointer
compile(node.expr()); compile(node.expr());
as.callAbsolute(ax()); as.callAbsolute(ax());
} }
// rewind stack // rewind stack; >4 bytes arguments are not supported.
// >4 bytes arguments are not supported.
rewindStack(as, stackSizeFromWordNum(node.numArgs())); rewindStack(as, stackSizeFromWordNum(node.numArgs()));
return null; return null;
} }

View File

@ -0,0 +1,15 @@
package net.loveruby.cflat.utils;
import java.util.List;
import java.util.ListIterator;
import java.util.ArrayList;
public abstract class ListUtils {
static public <T> List<T> reverse(List<T> list) {
List<T> result = new ArrayList<T>(list.size());
ListIterator<T> it = list.listIterator(list.size());
while (it.hasPrevious()) {
result.add(it.previous());
}
return result;
}
}

View File

@ -6,7 +6,8 @@ import org.junit.runners.Suite.*;
@RunWith(Suite.class) @RunWith(Suite.class)
@SuiteClasses({ @SuiteClasses({
TestCursor.class, TestCursor.class,
TestTextUtils.class TestTextUtils.class,
TestListUtils.class
}) })
public class TestAll { public class TestAll {
static public void main(String[] args) { static public void main(String[] args) {

27
unit/TestListUtils.java Normal file
View File

@ -0,0 +1,27 @@
import org.junit.*;
import org.junit.runner.*;
import static org.junit.Assert.*;
import java.util.List;
import java.util.ArrayList;
import static net.loveruby.cflat.utils.ListUtils.*;
public class TestListUtils {
static public void main(String[] args) {
JUnitCore.main(TestListUtils.class.getName());
}
@Test public void test_reverse() {
assertEquals("reverse #1", list(), reverse(list()));
assertEquals("reverse #2", list(1), reverse(list(1)));
assertEquals("reverse #3", list(2,1), reverse(list(1,2)));
assertEquals("reverse #4", list(3,2,1), reverse(list(1,2,3)));
}
private List<Integer> list(int... values) {
List<Integer> result = new ArrayList<Integer>();
for (int i : values) {
result.add(i);
}
return result;
}
}

View File

@ -10,8 +10,19 @@ public class TestTextUtils {
@Test public void test_dumpString() { @Test public void test_dumpString() {
assertEquals("dumpString #1", "\"\"", dumpString("")); assertEquals("dumpString #1", "\"\"", dumpString(""));
assertEquals("dumpString #2", "\"x\"", dumpString("x"));
assertEquals("dumpString #3", "\"xx\"", dumpString("xx"));
assertEquals("dumpString #4", "\"x\\\"x\"", dumpString("x\"x"));
assertEquals("dumpString #5", "\"x\\nx\"", dumpString("x\nx"));
} }
@Test public void test_isPrintable() { @Test public void test_isPrintable() {
assertEquals(true, isPrintable('a'));
assertEquals(true, isPrintable('A'));
assertEquals(true, isPrintable(' '));
assertEquals(false, isPrintable('\t'));
assertEquals(false, isPrintable('\r'));
assertEquals(false, isPrintable('\n'));
assertEquals(false, isPrintable('\0'));
} }
} }