diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/compiler/expr.zc | 33 | ||||
| -rw-r--r-- | src/lib/std.zc | 13 |
2 files changed, 40 insertions, 6 deletions
diff --git a/src/compiler/expr.zc b/src/compiler/expr.zc index a6cc55c..2cb36cf 100644 --- a/src/compiler/expr.zc +++ b/src/compiler/expr.zc @@ -409,9 +409,42 @@ int shifthint(int p, int v) { // function isn't defined yet) // 6. the result's type and class are set: .u functions return C_FRESH, which // is how the analyzer knows the caller now owns a new object +// std.Io.print(a, b, ...) and println: any mix of strings, byte strings, +// numbers and floats. each argument goes to the writer for its type; a fresh +// owned string is written and then freed. println ends with a line break. +int printcall(int line) { + int c; char* w; + expect(s_lp); + if (!is_op(s_rp)) { + while (1) { + c = expr(); rval(); + if (xty == tbstr || xstr) w = "std.Io.put_bs"; + else if (xfloat) w = "std.Io.put_f"; + else if (xty[0] == TY_PTR && xty[4] == tchar) w = "std.Io.put_s"; + else if (xty[0] == TY_ARR && xty[4] == tchar) w = "std.Io.put_s"; + else w = "std.Io.put_n"; + if (c == C_FRESH && fchk) { + if (!rt.eq_w(w, "std.Io.put_s") && !rt.eq_w(w, "std.Io.put_bs")) cerr("a new object can't be printed; bind it to a name first"); + lit(0); op(O_PICK); callname(intern(w)); op(O_DROP); callname(s_free); op(O_DROP); + } else { + if (c >= C_VAR && tracked(c - C_VAR)) touch(c - C_VAR); + callname(intern(w)); op(O_DROP); + } + if (!accept(s_comma)) break; + } + } + expect(s_rp); + if (line) { lit(10); callname(intern("rt.put_c")); op(O_DROP); } + lit(0); + lv = 0; lvk = LV_NONE; xty = tint; xzero = 0; xbor = -1; xconst = 0; + xfloat = 0; xstr = 0; xlenloc = -1; xstamp = 0; xaf = 0; + return C_PLAIN; +} int call(int s) { int np, tags = 0, ret = 0; word ft = stype[s]; word[8] bs; int rs, rhs_type = 0, kop, cp = callpos, original = s; word storage; int origin, temporary, owner; word origins, owner_fact; word requirements = effect_requirements, edges = effect_edges; + if (rt.eq_w(sname[s], "std.Io.print")) return printcall(0); + if (rt.eq_w(sname[s], "std.Io.println")) return printcall(1); borrow_depth++; if (sname[s] == s_new && skind[s] == K_FN) { peek(); diff --git a/src/lib/std.zc b/src/lib/std.zc index b206888..5c86aa6 100644 --- a/src/lib/std.zc +++ b/src/lib/std.zc @@ -421,15 +421,16 @@ struct Host { // called as std.Io.name(args). the writers go through rt.put_c, so a capture // (std.capture) sees their text too. the rt names (rt.put_n, rt.put_s and the // rest) stay; these are the same operations, grouped with the library. -// zc has no varargs or overloading, so print takes a string, and numbers have -// their own writers: std.Io.print("n = "); std.Io.put_n(n); std.Io.nl(); +// print and println take any mix of strings, byte strings, numbers and floats, +// each written by its type: std.Io.println("n = ", n, ", x = ", x); struct Io { - // writes a string. - // s: the text + // writes its arguments in order: any mix of strings, byte strings, numbers + // and floats (the compiler picks the writer for each argument's type). + // s: the first value; more may follow // returns: 0 static int print(char* s) { return rt.put_s(s); } - // writes a string and a line break. - // s: the text + // writes its arguments like print, then a line break. no arguments: just the line break. + // s: the first value; more may follow // returns: 0 static int println(char* s) { rt.put_s(s); return rt.put_c(10); } // writes a line break. |
