mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 18:36:31 +00:00
try add survery code coverage program 2
This commit is contained in:
parent
f8b573c135
commit
b96fe32201
@ -65,7 +65,7 @@ export type ExprKind =
|
|||||||
body: Expr;
|
body: Expr;
|
||||||
};
|
};
|
||||||
|
|
||||||
export type UnaryType = "not";
|
export type UnaryType = "not" | "-";
|
||||||
export type BinaryType =
|
export type BinaryType =
|
||||||
| "+"
|
| "+"
|
||||||
| "*"
|
| "*"
|
||||||
|
@ -629,6 +629,7 @@ const simpleUnaryOperations: {
|
|||||||
result?: VType;
|
result?: VType;
|
||||||
}[] = [
|
}[] = [
|
||||||
{ unaryType: "not", operand: { type: "bool" } },
|
{ unaryType: "not", operand: { type: "bool" } },
|
||||||
|
{ unaryType: "-", operand: { type: "int" } },
|
||||||
];
|
];
|
||||||
|
|
||||||
const simpleBinaryOperations: {
|
const simpleBinaryOperations: {
|
||||||
|
@ -47,7 +47,7 @@ export class Compiler {
|
|||||||
|
|
||||||
const lowerer = new Lowerer(lexer.currentPos());
|
const lowerer = new Lowerer(lexer.currentPos());
|
||||||
lowerer.lower(ast);
|
lowerer.lower(ast);
|
||||||
//lowerer.printProgram();
|
lowerer.printProgram();
|
||||||
const { program, fnNames } = lowerer.finish();
|
const { program, fnNames } = lowerer.finish();
|
||||||
|
|
||||||
return { program, fnNames };
|
return { program, fnNames };
|
||||||
|
@ -42,7 +42,7 @@ export function printStackTrace() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
throw new ReportNotAnError();
|
//throw new ReportNotAnError();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (!(error instanceof ReportNotAnError)) {
|
if (!(error instanceof ReportNotAnError)) {
|
||||||
throw error;
|
throw error;
|
||||||
|
@ -349,6 +349,18 @@ export class Lowerer {
|
|||||||
default:
|
default:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (vtype.type === "int") {
|
||||||
|
switch (expr.kind.unaryType) {
|
||||||
|
case "-": {
|
||||||
|
this.program.add(Ops.PushInt, 0);
|
||||||
|
this.program.add(Ops.PushInt, 1);
|
||||||
|
this.program.add(Ops.Subtract);
|
||||||
|
this.program.add(Ops.Multiply);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
}
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`unhandled unary` +
|
`unhandled unary` +
|
||||||
` '${vtypeToString(expr.vtype!)}' aka. ` +
|
` '${vtypeToString(expr.vtype!)}' aka. ` +
|
||||||
@ -378,6 +390,10 @@ export class Lowerer {
|
|||||||
case "==":
|
case "==":
|
||||||
this.program.add(Ops.Equal);
|
this.program.add(Ops.Equal);
|
||||||
return;
|
return;
|
||||||
|
case "!=":
|
||||||
|
this.program.add(Ops.Equal);
|
||||||
|
this.program.add(Ops.Not);
|
||||||
|
return;
|
||||||
case "<":
|
case "<":
|
||||||
this.program.add(Ops.LessThan);
|
this.program.add(Ops.LessThan);
|
||||||
return;
|
return;
|
||||||
@ -408,6 +424,10 @@ export class Lowerer {
|
|||||||
this.program.add(Ops.Or);
|
this.program.add(Ops.Or);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
if (expr.kind.binaryType === "and") {
|
||||||
|
this.program.add(Ops.And);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
throw new Error(
|
throw new Error(
|
||||||
`unhandled binaryType` +
|
`unhandled binaryType` +
|
||||||
|
@ -10,6 +10,7 @@ import {
|
|||||||
Param,
|
Param,
|
||||||
Stmt,
|
Stmt,
|
||||||
StmtKind,
|
StmtKind,
|
||||||
|
UnaryType,
|
||||||
} from "./ast.ts";
|
} from "./ast.ts";
|
||||||
import { printStackTrace, Reporter } from "./info.ts";
|
import { printStackTrace, Reporter } from "./info.ts";
|
||||||
import { Lexer } from "./lexer.ts";
|
import { Lexer } from "./lexer.ts";
|
||||||
@ -578,10 +579,11 @@ export class Parser {
|
|||||||
|
|
||||||
private parsePrefix(): Expr {
|
private parsePrefix(): Expr {
|
||||||
const pos = this.pos();
|
const pos = this.pos();
|
||||||
if (this.test("not")) {
|
if (this.test("not") || this.test("-")) {
|
||||||
|
const unaryType = this.current().type as UnaryType;
|
||||||
this.step();
|
this.step();
|
||||||
const subject = this.parsePrefix();
|
const subject = this.parsePrefix();
|
||||||
return this.expr({ type: "unary", unaryType: "not", subject }, pos);
|
return this.expr({ type: "unary", unaryType, subject }, pos);
|
||||||
}
|
}
|
||||||
return this.parsePostfix();
|
return this.parsePostfix();
|
||||||
}
|
}
|
||||||
|
230
examples/survey_code_coverage_program_2.slg
Normal file
230
examples/survey_code_coverage_program_2.slg
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
|
||||||
|
fn string_to_int_impl(text: string) -> int {
|
||||||
|
let base_2_digits = "01";
|
||||||
|
let base_8_digits = base_2_digits + "234567";
|
||||||
|
let base_10_digits = base_8_digits + "89";
|
||||||
|
let base_16_digits = base_10_digits + "abcdef";
|
||||||
|
|
||||||
|
let len = string_length(text);
|
||||||
|
if len == 0 {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
println("hello world");
|
||||||
|
|
||||||
|
if text[0] == "0"[0] {
|
||||||
|
if len == 1 {
|
||||||
|
0
|
||||||
|
} else if text[1] == "b"[0] {
|
||||||
|
parse_digits(string_slice(text, 2, -1), 2, base_2_digits)
|
||||||
|
} else if text[1] == "x"[0] {
|
||||||
|
parse_digits(string_slice(text, 2, -1), 16, base_16_digits)
|
||||||
|
} else {
|
||||||
|
parse_digits(string_slice(text, 1, -1), 8, base_8_digits)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
parse_digits(text, 10, base_10_digits)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn parse_digits(text: string, base: int, digit_set: string) -> int {
|
||||||
|
let val = 0;
|
||||||
|
let len = string_length(text);
|
||||||
|
for (let i = 0; i < len; i += 1) {
|
||||||
|
let ch = text[i];
|
||||||
|
if not string_contains(digit_set, ch) {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
val = val * base;
|
||||||
|
val += char_val(ch);
|
||||||
|
}
|
||||||
|
val
|
||||||
|
}
|
||||||
|
|
||||||
|
fn char_val(ch: int) -> int {
|
||||||
|
if ch >= "0"[0] and "9"[0] >= ch {
|
||||||
|
ch - "0"[0]
|
||||||
|
} else if ch >= "a"[0] and "f"[0] >= ch {
|
||||||
|
ch - "a"[0]
|
||||||
|
} else {
|
||||||
|
-1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test_string_to_int_impl() -> bool {
|
||||||
|
test("should convert zero", assert_int_equal(string_to_int_impl("0"), 0))
|
||||||
|
or test("should convert decimal", assert_int_equal(string_to_int_impl("10"), 10))
|
||||||
|
or test("should convert binary", assert_int_equal(string_to_int_impl("0b110"), 6))
|
||||||
|
or test("should convert octal", assert_int_equal(string_to_int_impl("071"), 51))
|
||||||
|
or test("should convert hexadecimal", assert_int_equal(string_to_int_impl("0xaa"), 170))
|
||||||
|
or test("should fail", assert_int_equal(string_to_int_impl("john"), -1))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn assert_int_equal(value: int, target: int) -> bool {
|
||||||
|
if value != target {
|
||||||
|
println("assertion failed: " + int_to_string(value) + " != " + int_to_string(target));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test(name: string, assertion: bool) -> bool {
|
||||||
|
println(" * test: " + name + " -> " + if assertion { "ok" } else { "failed" });
|
||||||
|
assertion
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let ok = test_string_to_int_impl();
|
||||||
|
if not ok {
|
||||||
|
println("tests failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
fn print(msg: string) #[builtin(Print)] {}
|
||||||
|
fn println(msg: string) { print(msg + "\n") }
|
||||||
|
|
||||||
|
fn int_to_string(number: int) -> string #[builtin(IntToString)] {}
|
||||||
|
|
||||||
|
fn string_push_char(str: string, value: int) -> string #[builtin(StringPushChar)] {}
|
||||||
|
fn string_char_at(str: string, index: int) -> int #[builtin(StringCharAt)] {}
|
||||||
|
fn string_length(str: string) -> int #[builtin(StringLength)] {}
|
||||||
|
fn string_to_int(str: string) -> int #[builtin(StringToInt)] {}
|
||||||
|
|
||||||
|
fn string_array_new() -> [string] #[builtin(ArrayNew)] {}
|
||||||
|
fn string_array_push(array: [string], value: string) #[builtin(ArrayPush)] {}
|
||||||
|
fn string_array_length(array: [string]) -> int #[builtin(ArrayLength)] {}
|
||||||
|
fn string_array_at(array: [string], index: int) -> string #[builtin(ArrayAt)] {}
|
||||||
|
|
||||||
|
fn int_array_new() -> [int] #[builtin(ArrayNew)] {}
|
||||||
|
fn int_array_push(array: [int], value: int) #[builtin(ArrayPush)] {}
|
||||||
|
fn int_array_length(array: [int]) -> int #[builtin(ArrayLength)] {}
|
||||||
|
fn int_array_at(array: [int], index: int) -> int #[builtin(ArrayAt)] {}
|
||||||
|
|
||||||
|
fn file_open(filename: string, mode: string) -> int #[builtin(FileOpen)] {}
|
||||||
|
fn file_close(file: int) #[builtin(FileClose)] {}
|
||||||
|
fn file_write_string(file: int, content: string) -> int #[builtin(FileWriteString)] {}
|
||||||
|
fn file_read_char(file: int) -> int #[builtin(FileReadChar)] {}
|
||||||
|
fn file_read_to_string(file: int) -> string #[builtin(FileReadToString)] {}
|
||||||
|
fn file_flush(file: int) #[builtin(FileFlush)] {}
|
||||||
|
fn file_eof(file: int) -> bool #[builtin(FileEof)] {}
|
||||||
|
|
||||||
|
|
||||||
|
fn stdin() -> int { 0 }
|
||||||
|
fn stdout() -> int { 1 }
|
||||||
|
fn stderr() -> int { 2 }
|
||||||
|
|
||||||
|
fn file_read_line(file: int) -> string {
|
||||||
|
let line = "";
|
||||||
|
loop {
|
||||||
|
if file_eof(file) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let ch = file_read_char(file);
|
||||||
|
if ch == "\n"[0] {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
line = string_push_char(line, ch);
|
||||||
|
}
|
||||||
|
line
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_text_file(filename: string) -> string {
|
||||||
|
let file = file_open(filename, "r");
|
||||||
|
let text = file_read_to_string(file);
|
||||||
|
file_close(file);
|
||||||
|
text
|
||||||
|
}
|
||||||
|
|
||||||
|
fn input(prompt: string) -> string {
|
||||||
|
print("> ");
|
||||||
|
file_flush(stdout());
|
||||||
|
file_read_line(stdin())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn string_abs(number: int) -> int {
|
||||||
|
let result = number;
|
||||||
|
if number < 0 {
|
||||||
|
result = number - (number * 2);
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn string_split(str: string, seperator: int) -> [string] {
|
||||||
|
let result: [string] = string_array_new();
|
||||||
|
|
||||||
|
let i = 0;
|
||||||
|
let current_str = "";
|
||||||
|
loop {
|
||||||
|
if i >= string_length(str) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
let char = str[i];
|
||||||
|
if char == seperator {
|
||||||
|
string_array_push(result, current_str);
|
||||||
|
current_str = "";
|
||||||
|
} else {
|
||||||
|
current_str = string_push_char(current_str, char);
|
||||||
|
}
|
||||||
|
i = i + 1;
|
||||||
|
}
|
||||||
|
string_array_push(result, current_str);
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn string_slice(str: string, from: int, to: int) -> string {
|
||||||
|
let result = "";
|
||||||
|
let len = string_length(str);
|
||||||
|
let actual_to =
|
||||||
|
if to >= len { len }
|
||||||
|
else if to < 0 { len - to }
|
||||||
|
else { to };
|
||||||
|
for (let i = from; i < actual_to; i += i) {
|
||||||
|
result = string_push_char(result, str[i]);
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn string_contains(str: string, ch: int) -> bool {
|
||||||
|
let len = string_length(str);
|
||||||
|
for (let i = 0; i < len; i += 1) {
|
||||||
|
if str[i] == ch {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
fn array_clone(array: [int]) -> [int] {
|
||||||
|
let len = int_array_length(array);
|
||||||
|
let result = int_array_new();
|
||||||
|
let i = 0;
|
||||||
|
loop {
|
||||||
|
if i >= len { break; }
|
||||||
|
int_array_push(result, array[i]);
|
||||||
|
i = 1 + 1;
|
||||||
|
}
|
||||||
|
result
|
||||||
|
}
|
||||||
|
|
||||||
|
fn array_sort_mut(array: [int]) {
|
||||||
|
let len = int_array_length(array);
|
||||||
|
for (let i = 0; i < len; i += 1) {
|
||||||
|
for (let j = i + 1; j < len; j += 1) {
|
||||||
|
if array[j] < array[i] {
|
||||||
|
let tmp = array[j];
|
||||||
|
array[j] = array[i];
|
||||||
|
array[i] = tmp;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn array_to_sorted(array: [int]) -> [int] {
|
||||||
|
let cloned = array_clone(array);
|
||||||
|
array_sort_mut(array);
|
||||||
|
cloned
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
22
stdlib.slg
22
stdlib.slg
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
fn print(msg: string) #[builtin(Print)] {}
|
fn print(msg: string) #[builtin(Print)] {}
|
||||||
fn println(msg: string) { print(msg + "\n") }
|
fn println(msg: string) { print(msg + "\n") }
|
||||||
|
|
||||||
@ -59,11 +60,7 @@ fn input(prompt: string) -> string {
|
|||||||
file_read_line(stdin())
|
file_read_line(stdin())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn char(ch: string) -> int {
|
fn string_abs(number: int) -> int {
|
||||||
ch[0]
|
|
||||||
}
|
|
||||||
|
|
||||||
fn abs(number: int) -> int {
|
|
||||||
let result = number;
|
let result = number;
|
||||||
if number < 0 {
|
if number < 0 {
|
||||||
result = number - (number * 2);
|
result = number - (number * 2);
|
||||||
@ -71,7 +68,7 @@ fn abs(number: int) -> int {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn split(str: string, seperator: int) -> [string] {
|
fn string_split(str: string, seperator: int) -> [string] {
|
||||||
let result: [string] = string_array_new();
|
let result: [string] = string_array_new();
|
||||||
|
|
||||||
let i = 0;
|
let i = 0;
|
||||||
@ -93,7 +90,7 @@ fn split(str: string, seperator: int) -> [string] {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
fn slice(str: string, from: int, to: int) -> string {
|
fn string_slice(str: string, from: int, to: int) -> string {
|
||||||
let result = "";
|
let result = "";
|
||||||
let i = from;
|
let i = from;
|
||||||
loop {
|
loop {
|
||||||
@ -109,6 +106,16 @@ fn slice(str: string, from: int, to: int) -> string {
|
|||||||
result
|
result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn string_contains(str: string, ch: int) -> bool {
|
||||||
|
let len = string_length(str);
|
||||||
|
for (let i = 0; i < len; i += 1) {
|
||||||
|
if str[i] == ch {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
fn array_clone(array: [int]) -> [int] {
|
fn array_clone(array: [int]) -> [int] {
|
||||||
let len = int_array_length(array);
|
let len = int_array_length(array);
|
||||||
let result = int_array_new();
|
let result = int_array_new();
|
||||||
@ -139,3 +146,4 @@ fn array_to_sorted(array: [int]) -> [int] {
|
|||||||
array_sort_mut(array);
|
array_sort_mut(array);
|
||||||
cloned
|
cloned
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user