@@ -16,33 +16,49 @@ const interpreter = @import("../interpreter.zig");
1616///
1717/// Returns:
1818/// An unspecified value, or an error if writing to stdout fails.
19- pub fn display (interp : * interpreter.Interpreter , _ : * core.Environment , args : core.ValueList , _ : * u64 ) ElzError ! Value {
20- if (args .items .len != 1 ) return ElzError .WrongArgumentCount ;
21- var buffer : [4096 ]u8 = undefined ;
22- const stdout_file = std .Io .File .stdout ();
23- var stdout_writer = stdout_file .writer (interp .io , & buffer );
24- const aw = & stdout_writer .interface ;
25- const value = args .items [0 ];
26-
19+ /// Renders a value in display mode (strings unquoted, chars as raw codepoints).
20+ fn render_display (value : Value , w : * std.Io.Writer ) ! void {
2721 switch (value ) {
28- .string = > | s | aw .writeAll (s ) catch return ElzError . ForeignFunctionError ,
22+ .string = > | s | try w .writeAll (s ),
2923 .character = > | c | {
3024 if (c > 0x10FFFF ) return ElzError .InvalidArgument ;
31-
3225 const codepoint : u21 = @intCast (c );
33- if (! std .unicode .utf8ValidCodepoint (codepoint )) {
34- return ElzError .InvalidArgument ;
35- }
36-
26+ if (! std .unicode .utf8ValidCodepoint (codepoint )) return ElzError .InvalidArgument ;
3727 var buf : [4 ]u8 = undefined ;
38- const len = std .unicode .utf8Encode (codepoint , & buf ) catch {
39- return ElzError .InvalidArgument ;
40- };
41- aw .writeAll (buf [0.. @as (usize , @intCast (len ))]) catch return ElzError .ForeignFunctionError ;
28+ const len = std .unicode .utf8Encode (codepoint , & buf ) catch return ElzError .InvalidArgument ;
29+ try w .writeAll (buf [0.. @as (usize , @intCast (len ))]);
4230 },
43- else = > writer .write (value , aw ) catch return ElzError .ForeignFunctionError ,
31+ else = > try writer .write (value , w ),
32+ }
33+ }
34+
35+ /// Writes the rendered bytes from `aw` either to stdout (when `port_opt` is null) or to
36+ /// the supplied port. The output is fully buffered and flushed at the end.
37+ fn flush_to_destination (interp : * interpreter.Interpreter , aw : * std.Io.Writer.Allocating , port_opt : ? Value ) ElzError ! void {
38+ const bytes = aw .written ();
39+ if (port_opt ) | port_val | {
40+ if (port_val != .port ) return ElzError .InvalidArgument ;
41+ port_val .port .writeString (bytes ) catch return ElzError .ForeignFunctionError ;
42+ return ;
4443 }
45- aw .flush () catch return ElzError .ForeignFunctionError ;
44+ var buffer : [4096 ]u8 = undefined ;
45+ const stdout_file = std .Io .File .stdout ();
46+ var stdout_writer = stdout_file .writer (interp .io , & buffer );
47+ const out = & stdout_writer .interface ;
48+ out .writeAll (bytes ) catch return ElzError .ForeignFunctionError ;
49+ out .flush () catch return ElzError .ForeignFunctionError ;
50+ }
51+
52+ pub fn display (interp : * interpreter.Interpreter , env : * core.Environment , args : core.ValueList , _ : * u64 ) ElzError ! Value {
53+ if (args .items .len < 1 or args .items .len > 2 ) return ElzError .WrongArgumentCount ;
54+ var aw : std.Io.Writer.Allocating = .init (env .allocator );
55+ defer aw .deinit ();
56+ render_display (args .items [0 ], & aw .writer ) catch | err | switch (err ) {
57+ ElzError .InvalidArgument = > return ElzError .InvalidArgument ,
58+ else = > return ElzError .ForeignFunctionError ,
59+ };
60+ const port_opt : ? Value = if (args .items .len == 2 ) args .items [1 ] else null ;
61+ try flush_to_destination (interp , & aw , port_opt );
4662 return Value .unspecified ;
4763}
4864
@@ -54,14 +70,13 @@ pub fn display(interp: *interpreter.Interpreter, _: *core.Environment, args: cor
5470///
5571/// Returns:
5672/// An unspecified value, or an error if writing to stdout fails.
57- pub fn write_proc (interp : * interpreter.Interpreter , _ : * core.Environment , args : core.ValueList , _ : * u64 ) ElzError ! Value {
58- if (args .items .len != 1 ) return ElzError .WrongArgumentCount ;
59- var buffer : [4096 ]u8 = undefined ;
60- const stdout_file = std .Io .File .stdout ();
61- var stdout_writer = stdout_file .writer (interp .io , & buffer );
62- const aw = & stdout_writer .interface ;
63- writer .write (args .items [0 ], aw ) catch return ElzError .ForeignFunctionError ;
64- aw .flush () catch return ElzError .ForeignFunctionError ;
73+ pub fn write_proc (interp : * interpreter.Interpreter , env : * core.Environment , args : core.ValueList , _ : * u64 ) ElzError ! Value {
74+ if (args .items .len < 1 or args .items .len > 2 ) return ElzError .WrongArgumentCount ;
75+ var aw : std.Io.Writer.Allocating = .init (env .allocator );
76+ defer aw .deinit ();
77+ writer .write (args .items [0 ], & aw .writer ) catch return ElzError .ForeignFunctionError ;
78+ const port_opt : ? Value = if (args .items .len == 2 ) args .items [1 ] else null ;
79+ try flush_to_destination (interp , & aw , port_opt );
6580 return Value .unspecified ;
6681}
6782
@@ -73,14 +88,13 @@ pub fn write_proc(interp: *interpreter.Interpreter, _: *core.Environment, args:
7388///
7489/// Returns:
7590/// An unspecified value, or an error if writing to stdout fails.
76- pub fn newline (interp : * interpreter.Interpreter , _ : * core.Environment , args : core.ValueList , _ : * u64 ) ElzError ! Value {
77- if (args .items .len != 0 ) return ElzError .WrongArgumentCount ;
78- var buffer : [4096 ]u8 = undefined ;
79- const stdout_file = std .Io .File .stdout ();
80- var stdout_writer = stdout_file .writer (interp .io , & buffer );
81- const aw = & stdout_writer .interface ;
82- aw .writeAll ("\n " ) catch return ElzError .ForeignFunctionError ;
83- aw .flush () catch return ElzError .ForeignFunctionError ;
91+ pub fn newline (interp : * interpreter.Interpreter , env : * core.Environment , args : core.ValueList , _ : * u64 ) ElzError ! Value {
92+ if (args .items .len > 1 ) return ElzError .WrongArgumentCount ;
93+ var aw : std.Io.Writer.Allocating = .init (env .allocator );
94+ defer aw .deinit ();
95+ aw .writer .writeAll ("\n " ) catch return ElzError .ForeignFunctionError ;
96+ const port_opt : ? Value = if (args .items .len == 1 ) args .items [0 ] else null ;
97+ try flush_to_destination (interp , & aw , port_opt );
8498 return Value .unspecified ;
8599}
86100
0 commit comments