diff --git a/ChangeLog b/ChangeLog index 454131e..f88b521 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,36 @@ +Sun Sep 14 02:27:56 2008 Minero Aoki + + * net/loveruby/cflat/compiler/TypeChecker.java: reject incomplete + multi-dimension array for function parameters. + + * net/loveruby/cflat/compiler/TypeChecker.java: reject array + variable definition without length. + + * net/loveruby/cflat/type/Type.java: remove #isAllocated. + + * net/loveruby/cflat/type/UserType.java: ditto. + + * net/loveruby/cflat/type/ArrayType.java: change #isAllocatedArray + semantics. isAllocatedArray requires the all consecutive array + types have its length, recursively. + + * net/loveruby/cflat/type/ArrayType.java: new method + #isIncompleteArray. + + * net/loveruby/cflat/compiler/Compiler.java: new option + --dump-asm. + + * net/loveruby/cflat/compiler/Compiler.java: handle "--" on + command line. + + * test/run.sh: use bash. + + * test/shunit.sh: show program name on core dump. + + * test/syntax1.cb: int[][] is now invalid. + + * cbci: print coredump and signal. + Sun Sep 14 00:13:37 2008 Minero Aoki * cbci: new command. Simple Cflat interpriter. diff --git a/cbci b/cbci index 162dad2..3ad4ea5 100755 --- a/cbci +++ b/cbci @@ -117,9 +117,7 @@ def interprit(path, verbose) exit 1 unless $? == 0 begin exe = File.basename(path, '.cb') - system "./#{exe}" - st = $? - $stderr.puts "status: #{st}" + invoke "./#{exe}", verbose exit 0 rescue SystemCallError => err error_exit err.message @@ -130,4 +128,31 @@ def interprit(path, verbose) end end +def invoke(cmd, verbose) + $stderr.puts cmd if verbose + system cmd + st = $? + show_status st if st.exitstatus != 0 or verbose + st +end + +module Signal # reopen + NAMES = Signal.list.invert + + def Signal.name(num) + NAMES[num] or raise ArgumentError, "undefined signal number" + end +end + +def show_status(st) + case + when st.coredump? + $stderr.puts "core dumped (SIG#{Signal.name(st.termsig)})" + when st.signaled? + $stderr.puts "terminated by signal (SIG#{Signal.name(st.termsig)})" + else + $stderr.puts "status: #{st.exitstatus}" + end +end + main diff --git a/net/loveruby/cflat/compiler/Compiler.java b/net/loveruby/cflat/compiler/Compiler.java index 525c7e3..aa73b65 100644 --- a/net/loveruby/cflat/compiler/Compiler.java +++ b/net/loveruby/cflat/compiler/Compiler.java @@ -71,7 +71,16 @@ public class Compiler { opts.loader = new LibraryLoader(); while (it.hasNext()) { String arg = (String)it.next(); - if (arg.startsWith("-")) { + if (arg.equals("-")) { + System.err.println("FIXME: stdin is not supported yet"); + System.exit(1); + } + else if (arg.equals("--")) { + // "--" Stops command line processing + it.remove(); + break; + } + else if (arg.startsWith("-")) { if (arg.equals("--check-syntax") || arg.equals("--dump-tokens") || arg.equals("--dump-ast") @@ -79,6 +88,7 @@ public class Compiler { || arg.equals("--dump-reference") || arg.equals("--dump-semantic") || arg.equals("-S") + || arg.equals("--dump-asm") || arg.equals("-c")) { if (opts.mode != null) { errorExit(opts.mode + " option and " @@ -141,6 +151,7 @@ public class Compiler { out.println(" --dump-ast Parses source file and dumps AST."); out.println(" --dump-semantic Checks semantics and dumps AST."); out.println(" -S Generates an assembly source."); + out.println(" --dump-asm Dumps an assembly source."); out.println(" -c Generates an object file."); out.println(" -I PATH Adds import file loading path."); out.println(" -o PATH Places output in file PATH."); @@ -208,6 +219,10 @@ public class Compiler { return; } String asm = CodeGenerator.generate(ast, opts.typeTable, errorHandler); + if (opts.isMode("--dump-asm")) { + System.out.println(asm); + return; + } writeFile(asmFileName(opts), asm); if (opts.isMode("-S")) { return; diff --git a/net/loveruby/cflat/compiler/TypeChecker.java b/net/loveruby/cflat/compiler/TypeChecker.java index f668fa2..6eda517 100644 --- a/net/loveruby/cflat/compiler/TypeChecker.java +++ b/net/loveruby/cflat/compiler/TypeChecker.java @@ -568,11 +568,12 @@ class TypeChecker extends Visitor { } protected boolean isInvalidParameterType(Type t) { - return t.isStruct() || t.isUnion() || t.isVoid(); + return t.isStruct() || t.isUnion() || t.isVoid() + || t.isIncompleteArray(); } protected boolean isInvalidVariableType(Type t) { - return t.isVoid(); + return t.isVoid() || (t.isArray() && ! t.isAllocatedArray()); } protected boolean isInvalidLHSType(Type t) { diff --git a/net/loveruby/cflat/type/ArrayType.java b/net/loveruby/cflat/type/ArrayType.java index 54aeb09..dd155d4 100644 --- a/net/loveruby/cflat/type/ArrayType.java +++ b/net/loveruby/cflat/type/ArrayType.java @@ -17,14 +17,21 @@ public class ArrayType extends Type { } public boolean isArray() { return true; } - public boolean isAllocated() { return length != undefined; } - public boolean isAllocatedArray() { return isAllocated(); } - public boolean isUnallocatedArray() { return !isAllocated(); } public boolean isDereferable() { return true; } - public boolean isPointerAlike() { return isUnallocatedArray(); } + public boolean isPointerAlike() { return length == undefined; } public boolean isScalar() { return true; } public boolean isSigned() { return false; } + public boolean isAllocatedArray() { + return length != undefined && + (!baseType.isArray() || baseType.isAllocatedArray()); + } + + public boolean isIncompleteArray() { + if (! baseType.isArray()) return false; + return !baseType.isAllocatedArray(); + } + public Type baseType() { return baseType; } @@ -40,11 +47,11 @@ public class ArrayType extends Type { // Value size as allocated array public long allocSize() { - if (isAllocated()) { - return baseType.allocSize() * length; + if (length == undefined) { + return size(); } else { - return size(); + return baseType.allocSize() * length; } } diff --git a/net/loveruby/cflat/type/Type.java b/net/loveruby/cflat/type/Type.java index 3d5febb..df1547e 100644 --- a/net/loveruby/cflat/type/Type.java +++ b/net/loveruby/cflat/type/Type.java @@ -17,8 +17,6 @@ public abstract class Type { { throw new Error("#isSigned for non-integer type"); } public boolean isPointer() { return false; } public boolean isArray() { return false; } - public boolean isAllocatedArray() { return false; } - public boolean isUnallocatedArray() { return false; } public boolean isComplexType() { return false; } public boolean isStruct() { return false; } public boolean isUnion() { return false; } @@ -28,6 +26,8 @@ public abstract class Type { // Ability methods (unary) public boolean isDereferable() { return false; } public boolean isPointerAlike() { return false; } + public boolean isAllocatedArray() { return false; } + public boolean isIncompleteArray() { return false; } public boolean isScalar() { return false; } public boolean isCallable() { return false; } diff --git a/net/loveruby/cflat/type/UserType.java b/net/loveruby/cflat/type/UserType.java index 0219af5..749913f 100644 --- a/net/loveruby/cflat/type/UserType.java +++ b/net/loveruby/cflat/type/UserType.java @@ -33,7 +33,6 @@ public class UserType extends NamedType { public boolean isPointer() { return realType().isPointer(); } public boolean isArray() { return realType().isArray(); } public boolean isAllocatedArray() { return realType().isAllocatedArray(); } - public boolean isUnallocatedArray() { return realType().isUnallocatedArray(); } public boolean isComplexType() { return realType().isComplexType(); } public boolean isStruct() { return realType().isStruct(); } public boolean isUnion() { return realType().isUnion(); } diff --git a/test/run.sh b/test/run.sh index ff04621..4ed66d2 100755 --- a/test/run.sh +++ b/test/run.sh @@ -1,4 +1,4 @@ -#!/usr/bin/ksh +#!/bin/bash main() { local pattern="." diff --git a/test/shunit.sh b/test/shunit.sh index 31effb1..35e9d12 100644 --- a/test/shunit.sh +++ b/test/shunit.sh @@ -59,7 +59,7 @@ assert_status() { expected=$1; shift shunit_invoke "$@" really=$? - assert_not_coredump || return + assert_not_coredump "$1" || return if [ "$really" != "$expected" ] then echo "shunit[$@]: status $expected expected but was: $really" @@ -73,7 +73,7 @@ assert_error() { shunit_begin_test shunit_invoke "$@" really=$? - assert_not_coredump || return + assert_not_coredump "$1" || return if [ "$really" = "0" ] then echo "shunit[$@]: non-zero status expected but was: $really" @@ -103,7 +103,7 @@ assert_equal() { mycmd=$2 eval "$excmd" >tc.out.expected 2>tc.err.expected eval "$mycmd" >tc.out.real 2>tc.err.real - assert_not_coredump || return + assert_not_coredump "$mycmd" || return cmp tc.out.real tc.out.expected >/dev/null 2>&1 if [ "$?" != "0" ] then @@ -135,7 +135,7 @@ assert_equal_stdout() { mycmd=$1; shift eval "$excmd" >tc.out.expected 2>/dev/null eval "$mycmd" >tc.out.real 2>/dev/null - assert_not_coredump || return + assert_not_coredump "$mycmd" || return cmp tc.out.real tc.out.expected >/dev/null 2>&1 if [ "$?" != "0" ] then @@ -152,7 +152,7 @@ assert_stdout() { expected=$1; shift echo "$expected" > tc.out.expected "$@" >tc.out.real 2>/dev/null - assert_not_coredump || return + assert_not_coredump "$1" || return cmp tc.out.expected tc.out.real >/dev/null 2>&1 if [ "$?" != "0" ] then @@ -166,22 +166,25 @@ assert_stdout() { rm -f core assert_not_coredump() { + local cmd="$1" + shunit_begin_test if [ -f core ] then - echo "core dumped: $mycmd" + echo "core dumped: $cmd" echo "----" shunit_test_failed + rm -f core return 1 fi - rm -f core return 0 } assert_not_exist() { + local file="$1"; shift + shunit_begin_test - file=$1; shift - if [ -f $file ] + if [ -f "$file" ] then echo "exists: $file" echo "----" @@ -192,9 +195,10 @@ assert_not_exist() { } assert_directory() { + local dir="$1"; shift + shunit_begin_test - dir=$1; shift - if [ ! -d $dir ] + if [ ! -d "$dir" ] then echo "not directory: $dir" echo "----" diff --git a/test/syntax1.cb b/test/syntax1.cb index eead570..52afdee 100644 --- a/test/syntax1.cb +++ b/test/syntax1.cb @@ -28,20 +28,18 @@ int*** ppp; int**** pppp; int***** ppppp; -int[] a; -int[][] aa; -int[][][] aaa; -int[][][][] aaaa; -int[][][][][] aaaaa; +int[1] a; +int[1][1] aa; +int[1][1][1] aaa; -int*[] pa; +int*[1] pa; int[]* ap; -int**[] ppa; +int**[1] ppa; int*[]* pap; int[]** app; -int[][]* aap; -int[]*[] apa; -int*[][] paa; +int[1][1]* aap; +int[]*[1] apa; +int*[1][1] paa; struct file { int fd; @@ -66,7 +64,7 @@ union node { typedef int myint; int -main(int argc, char[][] argv) +main(int argc, char** argv) { ff(); return f(1, 2, 3);