@@ -27,13 +27,150 @@ export const SEEK_SET = 0
2727export const SEEK_CUR = 1
2828export const SEEK_END = 2
2929
30+ // String functions
3031export def make_string(ptr: *char) -> string {
3132 var s: string
3233 s.value = ptr
3334 s.size = strlen(ptr) + 1
3435 return s
3536}
3637
38+ export type ToString = interface {
39+ def to_string -> &string
40+ }
41+
42+ // TODO remove special casing this
43+ export def == (a: string, b: string) -> bool {
44+ return strncmp(a.value, b.value, max(a.size - 1, b.size - 1) !size_t) == 0
45+ }
46+
47+ export def == (a: string, b: &string) -> bool {
48+ if b { return a == @b }
49+ return false
50+ }
51+
52+ export def == (a: &string, b: string) -> bool {
53+ if a { return @a == b }
54+ return false
55+ }
56+
57+ export def == (a: &string, b: &string) -> bool {
58+ if not a and not b { return true }
59+ if not a or not b { return false }
60+ return @a == @b
61+ }
62+
63+ export def + (a: &string, b: &string) -> &string {
64+ let ret = allocate(char, a.size + b.size - 1)
65+ defer delete(ret)
66+ memcopy(a.value, ret.value, a.size - 1)
67+ memcopy(b.value, ret.value ++ (a.size - 1), b.size - 1)
68+ ret[ret.size - 1] = 0
69+ return ret !&string
70+ }
71+
72+ export def + (a: &string, b: &ToString) -> &string {
73+ return a + b.to_string()
74+ }
75+
76+ export def += (a: &string, b: &ToString) -> &string {
77+ @a = @(a + b.to_string())
78+ return a
79+ }
80+
81+ export def + (a: &ToString, b: &string) -> &string {
82+ return a.to_string() + b
83+ }
84+
85+ // These are defined for better performance
86+ export def + (a: char, b: &string) -> &string {
87+ let ret = allocate(char, b.size + 1)
88+ defer delete(ret)
89+ memcopy(b.value, ret.value ++ 1, b.size - 1)
90+ ret[0] = a
91+ ret[ret.size - 1] = 0
92+ return ret !&string
93+ }
94+
95+ export def + (a: &string, b: char) -> &string {
96+ let ret = allocate(char, a.size + 1)
97+ defer delete(ret)
98+ memcopy(a.value, ret.value, a.size - 1)
99+ ret[ret.size - 2] = b
100+ ret[ret.size - 1] = 0
101+ return ret !&string
102+ }
103+
104+ export def += (a: &string, b: char) -> &string {
105+ @a = @(a + b)
106+ return a
107+ }
108+
109+ def to_string(sign: int, n: uint64) -> &string {
110+ let digits = "0123456789"
111+
112+ var str: &string = ""
113+ if n == 0 {
114+ str += '0'
115+ return str
116+ }
117+
118+ while n {
119+ str = digits[n % 10] + str
120+ n /= 10
121+ }
122+
123+ if sign < 0 {
124+ str = '-' + str
125+ }
126+
127+ return str
128+ }
129+
130+ export def to_string(a: &int64) -> &string {
131+ let n = -@a if @a < 0 else @a
132+ return to_string(1 if @a >= 0 else -1, n)
133+ }
134+
135+ export def to_string(a: &int32) -> &string {
136+ let n = -@a if @a < 0 else @a
137+ return to_string(1 if @a >= 0 else -1, n)
138+ }
139+
140+ export def to_string(a: &int16) -> &string {
141+ let n = -@a if @a < 0 else @a
142+ return to_string(1 if @a >= 0 else -1, n)
143+ }
144+
145+ export def to_string(a: &int8) -> &string {
146+ let n = -@a if @a < 0 else @a
147+ return to_string(1 if @a >= 0 else -1, n)
148+ }
149+
150+ export def to_string(a: &uint64) -> &string {
151+ return to_string(0, @a)
152+ }
153+
154+ export def to_string(a: &uint32) -> &string {
155+ return to_string(0, @a)
156+ }
157+
158+ export def to_string(a: &uint16) -> &string {
159+ return to_string(0, @a)
160+ }
161+
162+ export def to_string(a: &uint8) -> &string {
163+ return to_string(0, @a)
164+ }
165+
166+ export def to_string(a: &bool) -> &string {
167+ return "true" if @a else "false"
168+ }
169+
170+ export def to_string(a: &char) -> &string {
171+ return [@a]
172+ }
173+
37174export def print(args: &...) -> int {
38175 return fprint(stdout(), args)
39176}
@@ -42,7 +179,17 @@ export def error(args: &...) -> int {
42179 return fprint(stderr(), args)
43180}
44181
45- def print_val(file: File, tpe: *runtime::Type, value: *) -> int {
182+ def make_ref(tpe: *runtime::Type, value: *) -> runtime::Ref {
183+ var ref: runtime::Ref
184+ ref.tpe = runtime::reference(tpe)
185+ ref.value = value
186+ return ref
187+ }
188+
189+ def print_val(file: File, ref: runtime::Ref) -> int {
190+ let reftpe = runtime::ref_type(ref)
191+ let tpe = reftpe.tpe
192+ let value = ref.value
46193 if not tpe or not value {
47194 return cstd::fprintf(file, "%p".value, value)
48195 } else if tpe == string {
@@ -85,7 +232,7 @@ def print_val(file: File, tpe: *runtime::Type, value: *) -> int {
85232 return cstd::fprintf(file, "%p".value, @(value !**))
86233 } else if tpe.kind == runtime::TypeKind::REFERENCE {
87234 let v = value !*runtime::Ref
88- return print_val(file, tpe.tpe, v.value)
235+ return print_val(file, make_ref( tpe.tpe, v.value) )
89236 } else if tpe.kind == runtime::TypeKind::ARRAY {
90237 let arr = @(value !*[*])
91238 let size = arr.size
@@ -94,7 +241,7 @@ def print_val(file: File, tpe: *runtime::Type, value: *) -> int {
94241
95242 sum += cstd::fprintf(file, "[".value)
96243 for var i in 0..size {
97- sum += print_val(file, tpe.tpe, elements ++ i * tpe.tpe.size)
244+ sum += print_val(file, make_ref( tpe.tpe, elements ++ i * tpe.tpe.size) )
98245 if i < size - 1 {
99246 sum += cstd::fprintf(file, ", ".value)
100247 }
@@ -107,27 +254,13 @@ def print_val(file: File, tpe: *runtime::Type, value: *) -> int {
107254
108255 sum += cstd::fprintf(file, "[".value)
109256 for var i in 0..size {
110- sum += print_val(file, tpe.tpe, value ++ i * tpe.tpe.size)
257+ sum += print_val(file, make_ref( tpe.tpe, value ++ i * tpe.tpe.size) )
111258 if i < size - 1 {
112259 sum += cstd::fprintf(file, ", ".value)
113260 }
114261 }
115262 sum += cstd::fprintf(file, "]".value)
116263 return sum
117- } else if tpe.kind == runtime::TypeKind::STRUCT or tpe.kind == runtime::TypeKind::UNION {
118- let fields = tpe.fields
119- var sum = 0
120- sum += cstd::fprintf(file, "{".value)
121- for var i in 0..fields.size {
122- let field = fields[i]
123- sum += cstd::fprintf(file, "%s = ".value, field.name.value)
124- sum += print_val(file, field.tpe, value ++ field.offset)
125- if i < fields.size - 1 {
126- sum += cstd::fprintf(file, ", ".value)
127- }
128- }
129- sum += cstd::fprintf(file, "} !%s".value, tpe.name.value)
130- return sum
131264 } else if tpe.kind == runtime::TypeKind::ENUM {
132265 var v: int64 = 0
133266 for var i in 0..tpe.tpe.size {
@@ -142,14 +275,31 @@ def print_val(file: File, tpe: *runtime::Type, value: *) -> int {
142275 }
143276 }
144277 return cstd::fprintf(file, "%s".value, str.value)
278+ } else if runtime::implements(reftpe, ToString) {
279+ let str = (ref !&ToString).to_string()
280+ return cstd::fprintf(file, "%s".value, (@str).value)
281+ } else if tpe.kind == runtime::TypeKind::STRUCT or tpe.kind == runtime::TypeKind::UNION {
282+ let fields = tpe.fields
283+ var sum = 0
284+ sum += cstd::fprintf(file, "{".value)
285+ for var i in 0..fields.size {
286+ let field = fields[i]
287+ sum += cstd::fprintf(file, "%s = ".value, field.name.value)
288+ sum += print_val(file, make_ref(field.tpe, value ++ field.offset))
289+ if i < fields.size - 1 {
290+ sum += cstd::fprintf(file, ", ".value)
291+ }
292+ }
293+ sum += cstd::fprintf(file, "} !%s".value, tpe.name.value)
294+ return sum
145295 }
146296}
147297
148298export def fprint(file: File, args: &...) -> int {
149299 var sum = 0
150300 for var i in 0..args.size {
151301 let arg = args[i]
152- sum += print_val(file, runtime:: ref_type(arg).tpe, arg !*)
302+ sum += print_val(file, make_ref( ref_type(arg).tpe, arg !*) )
153303 }
154304 return sum
155305}
0 commit comments