Showing
9 changed files
with
227 additions
and
25 deletions
... | @@ -28,8 +28,14 @@ def _get_calculated(node): | ... | @@ -28,8 +28,14 @@ def _get_calculated(node): |
28 | return node | 28 | return node |
29 | 29 | ||
30 | inputfile = None | 30 | inputfile = None |
31 | +linenomap = {} | ||
31 | 32 | ||
32 | def _get_pos(prod) : | 33 | def _get_pos(prod) : |
34 | + if isinstance(prod, ply.lex.LexToken) : | ||
35 | + line_start = prod.lexer.lexdata.rfind('\n', 0, prod.lexpos) + 1 | ||
36 | + return {"lineno" : linenomap.get(prod.lineno, prod.lineno), | ||
37 | + "colno" : prod.lexpos - line_start + 1, | ||
38 | + "filename" : inputfile} | ||
33 | for p in prod.slice[1:] : | 39 | for p in prod.slice[1:] : |
34 | if isinstance(p, Node) and p.lineno : | 40 | if isinstance(p, Node) and p.lineno : |
35 | return p.getpos() | 41 | return p.getpos() |
... | @@ -38,7 +44,7 @@ def _get_pos(prod) : | ... | @@ -38,7 +44,7 @@ def _get_pos(prod) : |
38 | if isinstance(child, Node) and child.lineno : | 44 | if isinstance(child, Node) and child.lineno : |
39 | return child.getpos() | 45 | return child.getpos() |
40 | line_start = prod.lexer.lexdata.rfind('\n', 0, prod.lexpos(1)) + 1 | 46 | line_start = prod.lexer.lexdata.rfind('\n', 0, prod.lexpos(1)) + 1 |
41 | - return {"lineno" : prod.lineno(1), | 47 | + return {"lineno" : linenomap.get(prod.lineno(1), prod.lineno(1)), |
42 | "colno" : prod.lexpos(1) - line_start + 1, | 48 | "colno" : prod.lexpos(1) - line_start + 1, |
43 | "filename" : inputfile} | 49 | "filename" : inputfile} |
44 | 50 | ||
... | @@ -366,7 +372,7 @@ def p_empty(t): | ... | @@ -366,7 +372,7 @@ def p_empty(t): |
366 | pass | 372 | pass |
367 | 373 | ||
368 | def p_error(t): | 374 | def p_error(t): |
369 | - print("[%(filename):%(lineno)s:%(colno)s] syntax error:" % _get_pos(t)) | 375 | + print("[%(filename)s:%(lineno)s:%(colno)s] syntax error:" % _get_pos(t)) |
370 | start = t.lexer.lexdata.rfind("\n", 0, t.lexpos) | 376 | start = t.lexer.lexdata.rfind("\n", 0, t.lexpos) |
371 | if start == -1 : | 377 | if start == -1 : |
372 | start = 0 | 378 | start = 0 | ... | ... |
cctlib/cpp.py
0 → 100644
1 | +import subprocess | ||
2 | + | ||
3 | +def _lnomap (line) : | ||
4 | + if line.startswith("#") : | ||
5 | + try : | ||
6 | + return int(line.split(None, 2)[1]) | ||
7 | + except : | ||
8 | + pass | ||
9 | + | ||
10 | +def cpp (path, arch, args) : | ||
11 | + lmap = {} | ||
12 | + code = [] | ||
13 | + args = ["cpp", "-D__CCT__=%s" % arch] + args + [path] | ||
14 | + pos = 1 | ||
15 | + out = subprocess.check_output(args) | ||
16 | + for line in (l.rstrip() for l in out.decode().splitlines()) : | ||
17 | + num = _lnomap(line) | ||
18 | + if num is not None : | ||
19 | + pos = num | ||
20 | + else : | ||
21 | + code.append(line) | ||
22 | + lmap[len(code)] = pos | ||
23 | + pos += 1 | ||
24 | + return "\n".join(code), lmap | ||
25 | + | ||
26 | +def test (path) : | ||
27 | + old = [l.rstrip() for l in open(path)] | ||
28 | + new, lno = cpp(path, "x86", []) | ||
29 | + new = [l.rstrip() for l in new.splitlines()] | ||
30 | + for i, l in enumerate(new) : | ||
31 | + s = old[lno.get(i+1, i+1) - 1] | ||
32 | + if s != l : | ||
33 | + print("@%s -> %s" % (i+1, lno.get(i+1, i+1) - 1)) | ||
34 | + print("<", s) | ||
35 | + print(">", l) | ||
36 | + return old, new, lno |
... | @@ -581,8 +581,8 @@ def compile (path) : | ... | @@ -581,8 +581,8 @@ def compile (path) : |
581 | tgt = os.path.splitext(path)[0] + ".bios" | 581 | tgt = os.path.splitext(path)[0] + ".bios" |
582 | tgt, ["ttc", "asm", path, tgt] | 582 | tgt, ["ttc", "asm", path, tgt] |
583 | 583 | ||
584 | -def cpp (args, path) : | 584 | +def cpp (args) : |
585 | if args.test : | 585 | if args.test : |
586 | - return ["cpp", "-D", "TTC", path] | 586 | + return ["-DTTC"] |
587 | else : | 587 | else : |
588 | - return ["cpp", path] | 588 | + return [] | ... | ... |
... | @@ -450,7 +450,7 @@ class TypeCheckVisitor(Visitor): | ... | @@ -450,7 +450,7 @@ class TypeCheckVisitor(Visitor): |
450 | elif type_str == 'int': | 450 | elif type_str == 'int': |
451 | pass | 451 | pass |
452 | 452 | ||
453 | - def _compare_types(self, name_str, from_type, to_type, raise_errors=1): | 453 | + def _compare_types(self, name_str, from_type, to_type, raise_errors=1, node=None): |
454 | """Compares the two types to see if it's possible to perform a | 454 | """Compares the two types to see if it's possible to perform a |
455 | binary operation on them. If it is not, then the appropriate | 455 | binary operation on them. If it is not, then the appropriate |
456 | errors/warnings are raised, unless raise_errors is set to | 456 | errors/warnings are raised, unless raise_errors is set to |
... | @@ -472,14 +472,20 @@ class TypeCheckVisitor(Visitor): | ... | @@ -472,14 +472,20 @@ class TypeCheckVisitor(Visitor): |
472 | conflict = WARNING | 472 | conflict = WARNING |
473 | else: | 473 | else: |
474 | conflict = ERROR | 474 | conflict = ERROR |
475 | + elif from_str.startswith("pointer(") and to_str.startswith("pointer(") : | ||
476 | + conflict = WARNING | ||
475 | else: | 477 | else: |
476 | conflict = ERROR | 478 | conflict = ERROR |
477 | if not raise_errors: | 479 | if not raise_errors: |
478 | return conflict | 480 | return conflict |
479 | if conflict == WARNING: | 481 | if conflict == WARNING: |
480 | - self.warning("%s: Conversion from %s to %s may result in data loss." % (name_str, from_str, to_str)) | 482 | + self.warning("%s%s: Conversion from %s to %s may result in data loss." |
483 | + % ("[%s] " % node.loc() if node else "", | ||
484 | + name_str, from_str, to_str)) | ||
481 | elif conflict == ERROR: | 485 | elif conflict == ERROR: |
482 | - self.error("%s: Cannot convert from %s to %s." % (name_str, from_str, to_str)) | 486 | + self.error("%s%s: Cannot convert from %s to %s." |
487 | + % ("[%s] " % node.loc() if node else "", | ||
488 | + name_str, from_str, to_str)) | ||
483 | 489 | ||
484 | def vNode(self, node): | 490 | def vNode(self, node): |
485 | pass | 491 | pass |
... | @@ -519,7 +525,7 @@ class TypeCheckVisitor(Visitor): | ... | @@ -519,7 +525,7 @@ class TypeCheckVisitor(Visitor): |
519 | # TODO: re-implement this! | 525 | # TODO: re-implement this! |
520 | # elif node.left.symbol.is_constant: | 526 | # elif node.left.symbol.is_constant: |
521 | # self.error("Invalid lvalue: lvalue is constant!") | 527 | # self.error("Invalid lvalue: lvalue is constant!") |
522 | - self._compare_types("Assignment", node.right.type, node.left.type) | 528 | + self._compare_types("Assignment", node.right.type, node.left.type, node=node) |
523 | node.right.coerce_to_type = node.left.type | 529 | node.right.coerce_to_type = node.left.type |
524 | node.type = node.left.type | 530 | node.type = node.left.type |
525 | else: | 531 | else: |
... | @@ -527,15 +533,18 @@ class TypeCheckVisitor(Visitor): | ... | @@ -527,15 +533,18 @@ class TypeCheckVisitor(Visitor): |
527 | # specification for binary operand type coercion. | 533 | # specification for binary operand type coercion. |
528 | 534 | ||
529 | self._coerce_consts(node.left, node.right) | 535 | self._coerce_consts(node.left, node.right) |
530 | - left_conflicts = self._compare_types("", node.right.type, node.left.type, raise_errors=0) | 536 | + left_conflicts = self._compare_types("", node.right.type, node.left.type, |
531 | - right_conflicts = self._compare_types("", node.left.type, node.right.type, raise_errors=0) | 537 | + raise_errors=0, node=node) |
538 | + right_conflicts = self._compare_types("", node.left.type, node.right.type, | ||
539 | + raise_errors=0, node=node) | ||
532 | if left_conflicts < right_conflicts: | 540 | if left_conflicts < right_conflicts: |
533 | from_node = node.right | 541 | from_node = node.right |
534 | to_node = node.left | 542 | to_node = node.left |
535 | else: | 543 | else: |
536 | from_node = node.left | 544 | from_node = node.left |
537 | to_node = node.right | 545 | to_node = node.right |
538 | - self._compare_types("Binop '%s'" % node.op, from_node.type, to_node.type) | 546 | + self._compare_types("Binop '%s'" % node.op, from_node.type, to_node.type, |
547 | + node=node) | ||
539 | from_node.coerce_to_type = to_node.type | 548 | from_node.coerce_to_type = to_node.type |
540 | to_node.coerce_to_type = to_node.type | 549 | to_node.coerce_to_type = to_node.type |
541 | node.type = to_node.type | 550 | node.type = to_node.type |
... | @@ -550,7 +559,7 @@ class TypeCheckVisitor(Visitor): | ... | @@ -550,7 +559,7 @@ class TypeCheckVisitor(Visitor): |
550 | node.expr.accept(self) | 559 | node.expr.accept(self) |
551 | return_type = self.curr_func.type.get_return_type() | 560 | return_type = self.curr_func.type.get_return_type() |
552 | self._coerce_const(node.expr, return_type) | 561 | self._coerce_const(node.expr, return_type) |
553 | - self._compare_types("Return expression", node.expr.type, return_type) | 562 | + self._compare_types("Return expression", node.expr.type, return_type, node=node) |
554 | node.expr.coerce_to_type = return_type | 563 | node.expr.coerce_to_type = return_type |
555 | 564 | ||
556 | def vArrayExpression(self, node): | 565 | def vArrayExpression(self, node): |
... | @@ -579,7 +588,8 @@ class TypeCheckVisitor(Visitor): | ... | @@ -579,7 +588,8 @@ class TypeCheckVisitor(Visitor): |
579 | self.error("Too few arguments passed to function.") | 588 | self.error("Too few arguments passed to function.") |
580 | for arg, param in zip(node.arglist.nodes, params.nodes): | 589 | for arg, param in zip(node.arglist.nodes, params.nodes): |
581 | self._coerce_const(arg, param.type) | 590 | self._coerce_const(arg, param.type) |
582 | - self._compare_types("Function call argument", arg.type, param.type) | 591 | + self._compare_types("Function call argument", arg.type, param.type, |
592 | + node=node) | ||
583 | arg.coerce_to_type = param.type | 593 | arg.coerce_to_type = param.type |
584 | # If this function takes a variable number of args and | 594 | # If this function takes a variable number of args and |
585 | # we've got more args than required parameters, we need | 595 | # we've got more args than required parameters, we need | ... | ... |
... | @@ -1118,8 +1118,8 @@ def compile (path) : | ... | @@ -1118,8 +1118,8 @@ def compile (path) : |
1118 | tgt = os.path.splitext(path)[0] | 1118 | tgt = os.path.splitext(path)[0] |
1119 | return tgt, ["gcc", "-m32", "-o", tgt, path] | 1119 | return tgt, ["gcc", "-m32", "-o", tgt, path] |
1120 | 1120 | ||
1121 | -def cpp (args, path) : | 1121 | +def cpp (args) : |
1122 | if args.test : | 1122 | if args.test : |
1123 | - return ["cpp", "-D", "CC", path] | 1123 | + return ["-DCC"] |
1124 | else : | 1124 | else : |
1125 | - return ["cpp", path] | 1125 | + return [] | ... | ... |
1 | import argparse, sys, os, os.path, subprocess | 1 | import argparse, sys, os, os.path, subprocess |
2 | 2 | ||
3 | import ply.yacc as yacc | 3 | import ply.yacc as yacc |
4 | -from . import cparse, cvisitors, cx86, cttc | 4 | +from . import cparse, cvisitors, cx86, cttc, cpp |
5 | 5 | ||
6 | ARCH = {"x86" : cx86, | 6 | ARCH = {"x86" : cx86, |
7 | "ttc" : cttc} | 7 | "ttc" : cttc} |
... | @@ -19,15 +19,17 @@ class Compiler (object) : | ... | @@ -19,15 +19,17 @@ class Compiler (object) : |
19 | """This object encapsulates the front-end for the compiler and | 19 | """This object encapsulates the front-end for the compiler and |
20 | serves as a facade interface to the 'meat' of the compiler | 20 | serves as a facade interface to the 'meat' of the compiler |
21 | underneath.""" | 21 | underneath.""" |
22 | - def __init__ (self, arch, path, test) : | 22 | + def __init__ (self, arch, path, lmap, test) : |
23 | self.arch = arch | 23 | self.arch = arch |
24 | self.path = path | 24 | self.path = path |
25 | + self.lmap = lmap | ||
25 | self.test = test | 26 | self.test = test |
26 | self.total_errors = 0 | 27 | self.total_errors = 0 |
27 | self.total_warnings = 0 | 28 | self.total_warnings = 0 |
28 | def _parse (self) : | 29 | def _parse (self) : |
29 | "Parses the source code." | 30 | "Parses the source code." |
30 | cparse.inputfile = self.path | 31 | cparse.inputfile = self.path |
32 | + cparse.linenomap = self.lmap | ||
31 | self.ast = yacc.parse(self.code) | 33 | self.ast = yacc.parse(self.code) |
32 | def _compile_phase (self, visitor) : | 34 | def _compile_phase (self, visitor) : |
33 | "Applies a visitor to the abstract syntax tree." | 35 | "Applies a visitor to the abstract syntax tree." |
... | @@ -108,16 +110,14 @@ def main (args=None) : | ... | @@ -108,16 +110,14 @@ def main (args=None) : |
108 | ast_file = None | 110 | ast_file = None |
109 | if args.cpp : | 111 | if args.cpp : |
110 | print("Preprocessing %r" % src) | 112 | print("Preprocessing %r" % src) |
111 | - cpp = ARCH[args.arch].cpp(args, src) | 113 | + cppargs = ARCH[args.arch].cpp(args) |
112 | - print("..$ %s" % " ".join(cpp)) | 114 | + print("..$ cpp %s %s" % (" ".join(cppargs), src)) |
113 | - code = "\n".join(l.rstrip() | 115 | + code, lmap = cpp.cpp(src, args.arch, cppargs) |
114 | - for l in subprocess.check_output(cpp).decode().splitlines() | ||
115 | - if not l.startswith("#")) | ||
116 | print("Compiling preprocessed %r" % src) | 116 | print("Compiling preprocessed %r" % src) |
117 | else : | 117 | else : |
118 | code = "\n".join(l.rstrip() for l in open(src).readlines()) | 118 | code = "\n".join(l.rstrip() for l in open(src).readlines()) |
119 | print("Compiling %r" % src) | 119 | print("Compiling %r" % src) |
120 | - ret = Compiler(ARCH[args.arch], src, args.test).compile(code, ast_file) | 120 | + ret = Compiler(ARCH[args.arch], src, lmap, args.test).compile(code, ast_file) |
121 | if ast_file is not None : | 121 | if ast_file is not None : |
122 | ast_file.close() | 122 | ast_file.close() |
123 | if ret is None : | 123 | if ret is None : | ... | ... |
libc/stdio.asm
0 → 100644
libc/stdio.c
0 → 100644
1 | +#ifdef __CCT__ | ||
2 | +extern int putc(char c); | ||
3 | +#define neg(i) -i | ||
4 | +#define UINT(i) i | ||
5 | +#define _DIGITS "0123456789ABCDEF" | ||
6 | +#define _STR "65536" | ||
7 | +#else | ||
8 | +extern int putchar(int c); | ||
9 | +#define putc(c) putchar(c) | ||
10 | +#define neg(i) ~i + 1 | ||
11 | +#define UINT(i) (unsigned int)(i) | ||
12 | +#define _DIGITS _digits | ||
13 | +char _digits[17] = "0123456789ABCDEF"; | ||
14 | +#define _STR _str | ||
15 | +char _str[6] = "65536"; | ||
16 | +#endif | ||
17 | + | ||
18 | +int puts(char *s) { | ||
19 | + int n; | ||
20 | + int i; | ||
21 | + n = 0; | ||
22 | + i = 0; | ||
23 | + while (1) { | ||
24 | + if (s[i]) { | ||
25 | + n += putc(s[i]); | ||
26 | + i += 1; | ||
27 | + } else { | ||
28 | + break; | ||
29 | + } | ||
30 | + } | ||
31 | + return n; | ||
32 | +} | ||
33 | + | ||
34 | +#define ICHAR 105 | ||
35 | +#define SCHAR 115 | ||
36 | +#define UCHAR 117 | ||
37 | +#define XCHAR 120 | ||
38 | +#define PERCENT 37 | ||
39 | +#define MINUS 45 | ||
40 | + | ||
41 | +int putu(int u, char f) { | ||
42 | + char *DIGITS; | ||
43 | + char *str; | ||
44 | + int div; | ||
45 | + int r; | ||
46 | + int n; | ||
47 | + int p; | ||
48 | + DIGITS = _DIGITS; | ||
49 | + str = _STR; | ||
50 | + n = 0; | ||
51 | + p = 0; | ||
52 | + if (f == XCHAR) { | ||
53 | + div = 16; | ||
54 | + } else { | ||
55 | + div = 10; | ||
56 | + } | ||
57 | + while (u) { | ||
58 | + r = u % div; | ||
59 | + str[p] = DIGITS[r]; | ||
60 | + p += 1; | ||
61 | + u = u / div; | ||
62 | + } | ||
63 | + p -= 1; | ||
64 | + while (p >= 0) { | ||
65 | + n += putc(str[p]); | ||
66 | + p -= 1; | ||
67 | + } | ||
68 | + return n; | ||
69 | +} | ||
70 | + | ||
71 | +int puti(int i) { | ||
72 | + int n; | ||
73 | + int s; | ||
74 | + int r; | ||
75 | + n = 0; | ||
76 | + if (UINT(i) > 32767) { | ||
77 | + n += putc(MINUS); | ||
78 | + n += putu(neg(i), UCHAR); | ||
79 | + return n; | ||
80 | + } else { | ||
81 | + return putu(i, UCHAR); | ||
82 | + } | ||
83 | +} | ||
84 | + | ||
85 | +int printf(char *str, ...) { | ||
86 | + int n; | ||
87 | + int i; | ||
88 | + int a; | ||
89 | + int *iargs; | ||
90 | + char **cargs; | ||
91 | + iargs = &str; | ||
92 | + cargs = &str; | ||
93 | + a = 1; | ||
94 | + n = 0; | ||
95 | + i = 0; | ||
96 | + while (1) { | ||
97 | + if (str[i] == 0) { | ||
98 | + break; | ||
99 | + } else if (str[i] == PERCENT) { | ||
100 | + i += 1; | ||
101 | + if (str[i] == ICHAR) { | ||
102 | + n += puti(iargs[a]); | ||
103 | + } else if (str[i] == UCHAR) { | ||
104 | + n += putu(iargs[a], UCHAR); | ||
105 | + } else if (str[i] == SCHAR) { | ||
106 | + n += puts(cargs[a]); | ||
107 | + } else if (str[i] == XCHAR) { | ||
108 | + n += putu(iargs[a], XCHAR); | ||
109 | + } else if (str[i] == PERCENT) { | ||
110 | + n += putc(PERCENT); | ||
111 | + i += 1; | ||
112 | + continue; | ||
113 | + } else { | ||
114 | + n += putc(PERCENT); | ||
115 | + n += putc(str[i]); | ||
116 | + } | ||
117 | + a += 1; | ||
118 | + } else { | ||
119 | + n += putc(str[i]); | ||
120 | + } | ||
121 | + i += 1; | ||
122 | + } | ||
123 | + return n; | ||
124 | +} | ||
125 | + | ||
126 | +int main() { | ||
127 | + puts("hello world\n"); | ||
128 | + puti(42); | ||
129 | + puts(" => 42\n"); | ||
130 | + puti(-42); | ||
131 | + puts(" => -42\n"); | ||
132 | + putu(42, XCHAR); | ||
133 | + puts(" => 2A\n"); | ||
134 | + putu(42, UCHAR); | ||
135 | + puts(" => 42\n"); | ||
136 | + printf("hello %s I'm %u (%x)\n", "stdio", 42, 42); | ||
137 | + return 0; | ||
138 | +} |
libc/stdio.h
0 → 100644
-
Please register or login to post a comment