blob: 61f1675f3ee3ac2357d914fb22c3d4f0dcc9bd67 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
|
Union/Sum types
===============
How about allowing multiple `data` blocks with names:
For example, in file `Expr.slul`:
# Common data
data
int line
int column
end
data Unary
Expr op
end
data Binary
Expr op1
Expr op2
end
data IntegerLiteral
bool negative
uint64 value
end
data StringLiteral
# some kind of duplicate handling is necessary.
# maybe there should be a single identifier tree,
# and then a subtree if it's a union field.
# perhaps use (fieldname,union-index) as the key in the ident tree?
String value
end
func print
PrintWriter pw
int indent
# is this necessary? can't we just assume that all non-functions are
# instance variables?
# * in that case, maybe typeidents would need to be prefixed?
# * or, just require that fields are declared before functions
accesses
Unary.operand
Binary.operand1
Binary.operand2
IntegerLiteral.negative
IntegerLiteral.value
StringLiteral.value
code
print_indent pw indent
switch this.kind
case Unary
pw.print "unary("
op.print pw (indent+1)
case Binary
pw.print "binary("
op1.print pw (indent+1)
op2.print pw (indent+1)
case IntegerLiteral
pw.print "int_literal("
pw.print (switch negative [true "-"] [false ""]) number.to_str
case StringLiteral
pw.print "string_literal("
pw.string "\"" value.c_string_escape() "\""
end
pw.println ")"
# it could also be (would look nicer in this case, but if only
# printing from one function then it will not align as nicely)
")".println pw
# or, have some kind of special coroutine that yields stuff to print?
yield "unary("
yield (op.to_str (indent+1))
yield .newline
# alternatively, one could simply use different names:
pw.print "unary("
op.dump pw (indent+1)
# or
pw.print "unary("
op.print_to pw (indent+1)
end
More compact syntax:
data
int line
int column
case Unary
Expr op
case Binary
Expr op1
Expr op2
case IntegerLiteral
bool negative
uint64 value
case StringLiteral
# some kind of duplicate handling is necessary.
# maybe there should be a single identifier tree,
# and then a subtree if it's a union field.
# perhaps use (fieldname,union-index) as the key in the ident tree?
String value
end
func dump
io PrintWriter pw
int indent
code
dump_indent pw indent
specific
pw.println
case Unary
pw.print "unary("
op.print pw (indent+1)
case Binary
pw.print "binary("
op1.print pw (indent+1)
op2.print pw (indent+1)
case IntegerLiteral
pw.print "int_literal("
pw.print (switch negative [true "-"] [false ""]) number.to_str
case StringLiteral
pw.print "string_literal("
pw.string "\"" value.c_string_escape() "\""
end
Keyword
-------
* case
* only
* subtype
* when
|