feat: add M2 type checking and C emission

This commit is contained in:
2026-08-16 07:40:50 +09:00
parent 005056a5ea
commit da78a615fb
27 changed files with 1180 additions and 9 deletions
+9
View File
@@ -0,0 +1,9 @@
unit bad_arity;
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
fn main() -> i32 {
return add(1);
}
+7
View File
@@ -0,0 +1,7 @@
unit bad_assign;
fn main() -> i32 {
let value: i32 = 1;
value = 2;
return value;
}
+6
View File
@@ -0,0 +1,6 @@
unit bad_cast;
fn main() -> i32 {
let x: i32 = true as i32;
return x;
}
+6
View File
@@ -0,0 +1,6 @@
unit bad_condition;
fn main() -> i32 {
if 1 { return 0; }
return 1;
}
+5
View File
@@ -0,0 +1,5 @@
unit bad_return;
fn main() -> i32 {
return true;
}
+9
View File
@@ -0,0 +1,9 @@
unit bad_types;
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
fn main() -> i32 {
return add(true, 1);
}
+6
View File
@@ -0,0 +1,6 @@
unit bad_uninit;
fn main() -> i32 {
var value: i32;
return value;
}
+5
View File
@@ -0,0 +1,5 @@
unit bad_unknown;
fn main() -> i32 {
return missing_name;
}
+10
View File
@@ -0,0 +1,10 @@
unit bad_void;
fn noop() {
return;
}
fn main() -> i32 {
let value: i32 = noop();
return value;
}
+11
View File
@@ -0,0 +1,11 @@
unit cast_while;
pub fn main() -> i32 {
var x: i16 = 0;
while x < 3 {
x += 1;
}
let y: i32 = x as i32;
if y == 3 { return 0; }
return 1;
}
+23
View File
@@ -0,0 +1,23 @@
unit hello;
fn add(a: i32, b: i32) -> i32 {
return a + b;
}
fn is_answer(value: i32) -> bool {
return value == 42;
}
fn touch() {
return;
}
pub fn main() -> i32 {
touch();
let value: i32 = add(20, 22);
if is_answer(value) {
return 0;
} else {
return 1;
}
}
+15
View File
@@ -0,0 +1,15 @@
unit scopes;
fn register(switch: i32) -> i32 {
let auto: i32 = switch;
if true {
let auto: i32 = auto + 1;
if auto == 2 { return 0; }
}
if auto == 1 { return 0; }
return 1;
}
pub fn main() -> i32 {
return register(1);
}
+22
View File
@@ -18,3 +18,25 @@ for f in "$root"/tests/fail/*.fe; do
ok=$((ok+1))
done
echo "M1 tests: $ok cases passed"
m2tmp=$(mktemp -d)
trap 'rm -rf "$m2tmp"' EXIT HUP INT TERM
"$root"/fec --emit-c "$root"/tests/m2/hello.fe -o "$m2tmp/hello.c"
${CC:-cc} -std=c89 -pedantic "$m2tmp/hello.c" -o "$m2tmp/hello"
"$m2tmp/hello"
"$root"/fec --target=bits16 --emit-c "$root"/tests/m2/hello.fe -o "$m2tmp/hello16.c"
${CC:-cc} -std=c89 -pedantic "$m2tmp/hello16.c" -o "$m2tmp/hello16"
"$m2tmp/hello16"
"$root"/fec --emit-c "$root"/tests/m2/cast-while.fe -o "$m2tmp/cast.c"
${CC:-cc} -std=c89 -pedantic "$m2tmp/cast.c" -o "$m2tmp/cast"
"$m2tmp/cast"
"$root"/fec --emit-c "$root"/tests/m2/scopes.fe -o "$m2tmp/scopes.c"
${CC:-cc} -std=c89 -pedantic "$m2tmp/scopes.c" -o "$m2tmp/scopes"
"$m2tmp/scopes"
for f in bad-condition bad-cast bad-assign bad-unknown bad-arity bad-types bad-return bad-uninit bad-void; do
if "$root"/fec --emit-c "$root"/tests/m2/$f.fe -o "$m2tmp/$f.c" >/dev/null 2>/dev/null; then
echo "FAIL (accepted M2 semantic error): $f.fe"
exit 1
fi
done
echo "M2 tests: integer control-flow smoke passed"