mirror of https://github.com/aamine/cbc
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:
parent
e002c1089a
commit
a54e95aa16
20
ChangeLog
20
ChangeLog
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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()) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue