diff --git a/cogs/clos/clos.scm b/cogs/clos/clos.scm index fb1e8fa99..040ddf74d 100644 --- a/cogs/clos/clos.scm +++ b/cogs/clos/clos.scm @@ -1,223 +1,223 @@ -; ;; ---------------------------- Class Object definitions -------------------------------------------- - -; (struct Class-Object (name parents interfaces fields methods) #:mutable #:transparent) -; (struct Interface (name methods)) -; (struct Class-Instance (class-object fields) #:transparent) - -; (define (list-subset? left right) -; (hashset-subset? (list->hashset left) (list->hashset right))) - -; ;; Classes contain: -; ;; A name, which is required to be a symbol (string should also work, but for now a symbol simplifies this) -; ;; The parents are a list of class objects -> we don't want classes pointing to arbitrary objects -; ;; The fields are represented by a list of symbols, to refer to using the get-slot method -; ;; The methods in theory could be anything, as long as they're functions. -; ;; -; ;; Here we don't restrict the hash map of symbol -> function, but rather will restrict it on the -; ;; function when adding the methods. -; (define/contract (Class name parents interfaces fields methods) -; (->/c symbol? (listof Class-Object?) (listof Interface?) (listof symbol?) hash? Class-Object?) -; (unless (list-subset? -; ;; Collect the list of required methods for the given interfaces -; (transduce interfaces (flat-mapping Interface-methods) (into-list)) -; ;; Extract the methods that have been defined concretely on this class at construction -; (hash-keys->list methods)) -; (error! "Not all required methods are implemented for the given interfaces")) - -; (Class-Object name -; parents -; interfaces -; ;; Explicitly go collect the fields to flatten into this class given the -; ;; class hierarchy -; (combine-local-and-parent-fields fields parents) -; methods)) - -; (define (Make-Class name -; #:fields (fields '()) -; #:methods (methods '()) -; #:parents (parents '()) -; #:interfaces (interfaces '())) -; (Class name parents interfaces fields methods)) - -; (define (contains-duplicates? lst) -; (not (equal? (hashset-length (apply hashset lst)) (length lst)))) - -; ;; Flatten the incoming list -; (define (flatten lst) -; (transduce lst (flattening) (into-list))) - -; (define (collect-fields list-of-class-objects) -; (transduce list-of-class-objects (flat-mapping Class-Object-fields) (into-list))) - -; (define (combine-local-and-parent-fields local-fields list-of-class-objects) -; (let ([appended (append local-fields (collect-fields list-of-class-objects))]) -; (if (contains-duplicates? appended) (error! "Class field is unresolvable") appended))) - -; ;; ----------------------------------------------------------------------------------------------------- - -; ;; Add a method to a class -; ;; This can also occur in the root definition of the object in the hash, but the contract -; ;; won't be checked there at the moment TODO -; (define/contract (define-method class-object name method) -; (->/c Class-Object? symbol? function? any/c) -; (let ([methods (Class-Object-methods class-object)]) -; (set-Class-Object-methods! class-object (hash-insert methods name method)))) - -; (define (resolve-parent-method class-object name) -; (let ([possible-methods (map (lambda (x) (get-method x name)) (Class-Object-parents class-object))]) -; (if (equal? 1 (length possible-methods)) -; (car possible-methods) -; (error! "Unable to resolve the method on the class instance")))) - -; ;; Attempt to resolve the method on the class object via the class hierarchy -; ;; This checks the current class object, and then attempt to resolve the method upwards, returning the first -; ;; one that it finds. If there are multiple candidates, we bail and error out since we can't determine -; ;; which method we intended to call. -; (define/contract (get-method class-object name) -; (->/c Class-Object? symbol? function?) -; (let ([local-method (-> class-object (Class-Object-methods) (hash-try-get name))]) -; ;; If _this_ class object contains the method, then we return this method -; ;; This way we always select the correct method in the class hierarchy -; (if local-method -; local-method -; ;; Otherwise, attempt to resolve the method on the parents -; ;; For now, methods are just a hashmap from name -> method -; (resolve-parent-method class-object name)))) - -; ;; Attempt to resolve the method on the parent class to this class objects -; (define/contract (get-super-method class-object name) -; (->/c Class-Object? symbol? function?) -; (resolve-parent-method class-object name)) - -; (define/contract (position? lst value) -; (->/c list? any/c integer?) -; (define list-length (length lst)) -; (define (loop lst idx) -; (cond -; [(= idx list-length) -; => -; (error! "Value not a member of the list")] -; [(equal? value (list-ref lst idx)) -; => -; idx] -; [else -; => -; (loop lst (+ idx 1))])) -; (loop lst 0)) - -; ;; Map the given field name to an index in the class' slot -; (define/contract (%get-slot-idx class-object field-name) -; (->/c Class-Object? symbol? integer?) -; (-> class-object (Class-Object-fields) (position? field-name))) - -; ;; This returns whatever value is found in the slot -; ;; This _could_ be any value. TODO: find a way to bind a contract to a slot -; (define/contract (get-slot class-instance field-name) -; (->/c Class-Instance? symbol? any/c) -; (mut-vector-ref (Class-Instance-fields class-instance) -; (%get-slot-idx (Class-Instance-class-object class-instance) field-name))) - -; ;; Sets the slot in the class instance found a `field-name` to `value` -; ;; TODO: make the contract be dependent to have the result match the value's contract -; (define/contract (set-slot! class-instance field-name value) -; (->/c Class-Instance? symbol? any/c any/c) -; (vector-set! (Class-Instance-fields class-instance) -; ;; Get the slot index -> maps the field name to the index in the vector -; (%get-slot-idx (Class-Instance-class-object class-instance) field-name) -; value)) - -; ;; Instances should be represented in memory (for now) just as tagged vectors -; ;; Each of the fields will be zero'd out -; (define/contract (%allocate-instance class-object) -; (->/c Class-Object? Class-Instance?) -; ;; We can just use a normal vector here, not a mutable vector -; ;; Reference to the class object here -; (Class-Instance class-object -; ;; Fields as a mutable vector -; ;; Name resolution should be done via %get-slot method -; (apply mutable-vector (map (lambda (x) void) (Class-Object-fields class-object))))) - -; ;; Get the method on the class object denoted by the method name -; ;; and call it given the arguments here -; ;; TODO: figure out contracts for multi arity functions -; (define (call class-instance method-name . args) -; (apply (get-method (Class-Instance-class-object class-instance) method-name) -; ;; The instance is always an implicit first argument, and as such gets -; ;; cons onto the first of the arguments to call the function -; (cons class-instance args))) - -; ;; Same as above, calls the method on the nearest parent object -; (define (call-super class-instance method-name . args) -; (apply (get-super-method (Class-Instance-class-object class-instance) method-name) -; (cons class-instance args))) - -; (define/contract (class-instance-name class-instance) -; (->/c Class-Instance? symbol?) -; (Class-Object-name (Class-Instance-class-object class-instance))) - -; ;; TODO -> check if object implements interface -; ;; (define/contract (class-implements-Interface? class-instance interface) -; ;; (->/c Class-Object? Interface? boolean?) -; ;; (member? interface -; ;; - -; ;; ------------------- Examples -------------------------- - -; ;; Base object for everything in the class hierarchy -; (define Object -; (Class 'Object -; '() -; '() -; '() -; (hash 'println -; (lambda (self) -; (displayln (-> "#<" -; (string-append (symbol->string (class-instance-name self))) -; (string-append ">"))))))) - -; ;; Define the class object for Animal -; ;; Is a child of the Object base class -; (define Animal -; (Class 'Animal -; (list Object) -; '() -; '(name color weight) -; (hash 'get-weight (lambda (self) (get-slot self 'weight))))) - -; ;; Dog inherits from Animal, adds on the 'good-boy? field -; (define Dog (Class 'Dog (list Animal) '() '(good-boy?) (hash))) - -; ;; TODO: Once keyword arguments are a thing, classes could be defined like so: -; ;; (define Dog (Class #:name 'Dog -; ;; #:parents (list Animal) -; ;; #:interfaces '() -; ;; #:fields '(good-boy?) -; ;; #:methods (hash))) - -; ;; Allocates a new instance of a dog - here all of the fields are default to # -; (define sherman (%allocate-instance Dog)) -; ;; Set the weight to be 25 -> this is set in the instance, and all fields are flattened on construction -; (set-slot! sherman 'weight 25) -; ;; This will traverse upwards on the methods to find the method -; (call sherman 'println) -; ;; This should find the method on the parent class -; (call sherman 'get-weight) -; ;; Explicitly call the method on the super -; (call-super sherman 'get-weight) -; ;; Setting a slot since the default allocation of the instance sets everything to void -; (set-slot! sherman 'good-boy? #true) - -; (define Stinky (Interface 'Stinky '(smelly icky))) - -; (define Worm -; (Class 'Worm -; (list Dog) -; (list Stinky) -; '() -; (hash 'smelly (lambda (self) "Smelly!") 'icky (lambda (self) "Icky!")))) - -; (define New-Worm -; (Make-Class 'Worm -; #:parents (list Dog) -; #:interfaces (list Stinky) -; #:methods (hash 'smelly (lambda (self) "Smelly!") 'icky (lambda (self) "Icky!")))) +;; ---------------------------- Class Object definitions -------------------------------------------- + +(struct Class-Object (name parents interfaces fields methods) #:mutable #:transparent) +(struct Interface (name methods)) +(struct Class-Instance (class-object fields) #:transparent) + +(define (list-subset? left right) + (hashset-subset? (list->hashset left) (list->hashset right))) + +;; Classes contain: +;; A name, which is required to be a symbol (string should also work, but for now a symbol simplifies this) +;; The parents are a list of class objects -> we don't want classes pointing to arbitrary objects +;; The fields are represented by a list of symbols, to refer to using the get-slot method +;; The methods in theory could be anything, as long as they're functions. +;; +;; Here we don't restrict the hash map of symbol -> function, but rather will restrict it on the +;; function when adding the methods. +(define/contract (Class name parents interfaces fields methods) + (->/c symbol? (listof Class-Object?) (listof Interface?) (listof symbol?) hash? Class-Object?) + (unless (list-subset? + ;; Collect the list of required methods for the given interfaces + (transduce interfaces (flat-mapping Interface-methods) (into-list)) + ;; Extract the methods that have been defined concretely on this class at construction + (hash-keys->list methods)) + (error! "Not all required methods are implemented for the given interfaces")) + + (Class-Object name + parents + interfaces + ;; Explicitly go collect the fields to flatten into this class given the + ;; class hierarchy + (combine-local-and-parent-fields fields parents) + methods)) + +(define (Make-Class name + #:fields (fields '()) + #:methods (methods '()) + #:parents (parents '()) + #:interfaces (interfaces '())) + (Class name parents interfaces fields methods)) + +(define (contains-duplicates? lst) + (not (equal? (hashset-length (apply hashset lst)) (length lst)))) + +;; Flatten the incoming list +(define (flatten lst) + (transduce lst (flattening) (into-list))) + +(define (collect-fields list-of-class-objects) + (transduce list-of-class-objects (flat-mapping Class-Object-fields) (into-list))) + +(define (combine-local-and-parent-fields local-fields list-of-class-objects) + (let ([appended (append local-fields (collect-fields list-of-class-objects))]) + (if (contains-duplicates? appended) (error! "Class field is unresolvable") appended))) + +;; ----------------------------------------------------------------------------------------------------- + +;; Add a method to a class +;; This can also occur in the root definition of the object in the hash, but the contract +;; won't be checked there at the moment TODO +(define/contract (define-method class-object name method) + (->/c Class-Object? symbol? function? any/c) + (let ([methods (Class-Object-methods class-object)]) + (set-Class-Object-methods! class-object (hash-insert methods name method)))) + +(define (resolve-parent-method class-object name) + (let ([possible-methods (map (lambda (x) (get-method x name)) (Class-Object-parents class-object))]) + (if (equal? 1 (length possible-methods)) + (car possible-methods) + (error! "Unable to resolve the method on the class instance")))) + +;; Attempt to resolve the method on the class object via the class hierarchy +;; This checks the current class object, and then attempt to resolve the method upwards, returning the first +;; one that it finds. If there are multiple candidates, we bail and error out since we can't determine +;; which method we intended to call. +(define/contract (get-method class-object name) + (->/c Class-Object? symbol? function?) + (let ([local-method (-> class-object (Class-Object-methods) (hash-try-get name))]) + ;; If _this_ class object contains the method, then we return this method + ;; This way we always select the correct method in the class hierarchy + (if local-method + local-method + ;; Otherwise, attempt to resolve the method on the parents + ;; For now, methods are just a hashmap from name -> method + (resolve-parent-method class-object name)))) + +;; Attempt to resolve the method on the parent class to this class objects +(define/contract (get-super-method class-object name) + (->/c Class-Object? symbol? function?) + (resolve-parent-method class-object name)) + +(define/contract (position? lst value) + (->/c list? any/c integer?) + (define list-length (length lst)) + (define (loop lst idx) + (cond + [(= idx list-length) + => + (error! "Value not a member of the list")] + [(equal? value (list-ref lst idx)) + => + idx] + [else + => + (loop lst (+ idx 1))])) + (loop lst 0)) + +;; Map the given field name to an index in the class' slot +(define/contract (%get-slot-idx class-object field-name) + (->/c Class-Object? symbol? integer?) + (-> class-object (Class-Object-fields) (position? field-name))) + +;; This returns whatever value is found in the slot +;; This _could_ be any value. TODO: find a way to bind a contract to a slot +(define/contract (get-slot class-instance field-name) + (->/c Class-Instance? symbol? any/c) + (mut-vector-ref (Class-Instance-fields class-instance) + (%get-slot-idx (Class-Instance-class-object class-instance) field-name))) + +;; Sets the slot in the class instance found a `field-name` to `value` +;; TODO: make the contract be dependent to have the result match the value's contract +(define/contract (set-slot! class-instance field-name value) + (->/c Class-Instance? symbol? any/c any/c) + (vector-set! (Class-Instance-fields class-instance) + ;; Get the slot index -> maps the field name to the index in the vector + (%get-slot-idx (Class-Instance-class-object class-instance) field-name) + value)) + +;; Instances should be represented in memory (for now) just as tagged vectors +;; Each of the fields will be zero'd out +(define/contract (%allocate-instance class-object) + (->/c Class-Object? Class-Instance?) + ;; We can just use a normal vector here, not a mutable vector + ;; Reference to the class object here + (Class-Instance class-object + ;; Fields as a mutable vector + ;; Name resolution should be done via %get-slot method + (apply mutable-vector (map (lambda (x) void) (Class-Object-fields class-object))))) + +;; Get the method on the class object denoted by the method name +;; and call it given the arguments here +;; TODO: figure out contracts for multi arity functions +(define (call class-instance method-name . args) + (apply (get-method (Class-Instance-class-object class-instance) method-name) + ;; The instance is always an implicit first argument, and as such gets + ;; cons onto the first of the arguments to call the function + (cons class-instance args))) + +;; Same as above, calls the method on the nearest parent object +(define (call-super class-instance method-name . args) + (apply (get-super-method (Class-Instance-class-object class-instance) method-name) + (cons class-instance args))) + +(define/contract (class-instance-name class-instance) + (->/c Class-Instance? symbol?) + (Class-Object-name (Class-Instance-class-object class-instance))) + +;; TODO -> check if object implements interface +;; (define/contract (class-implements-Interface? class-instance interface) +;; (->/c Class-Object? Interface? boolean?) +;; (member? interface +;; + +;; ------------------- Examples -------------------------- + +;; Base object for everything in the class hierarchy +(define Object + (Class 'Object + '() + '() + '() + (hash 'println + (lambda (self) + (displayln (-> "#<" + (string-append (symbol->string (class-instance-name self))) + (string-append ">"))))))) + +;; Define the class object for Animal +;; Is a child of the Object base class +(define Animal + (Class 'Animal + (list Object) + '() + '(name color weight) + (hash 'get-weight (lambda (self) (get-slot self 'weight))))) + +;; Dog inherits from Animal, adds on the 'good-boy? field +(define Dog (Class 'Dog (list Animal) '() '(good-boy?) (hash))) + +;; TODO: Once keyword arguments are a thing, classes could be defined like so: +;; (define Dog (Class #:name 'Dog +;; #:parents (list Animal) +;; #:interfaces '() +;; #:fields '(good-boy?) +;; #:methods (hash))) + +;; Allocates a new instance of a dog - here all of the fields are default to # +(define sherman (%allocate-instance Dog)) +;; Set the weight to be 25 -> this is set in the instance, and all fields are flattened on construction +(set-slot! sherman 'weight 25) +;; This will traverse upwards on the methods to find the method +(call sherman 'println) +;; This should find the method on the parent class +(call sherman 'get-weight) +;; Explicitly call the method on the super +(call-super sherman 'get-weight) +;; Setting a slot since the default allocation of the instance sets everything to void +(set-slot! sherman 'good-boy? #true) + +(define Stinky (Interface 'Stinky '(smelly icky))) + +(define Worm + (Class 'Worm + (list Dog) + (list Stinky) + '() + (hash 'smelly (lambda (self) "Smelly!") 'icky (lambda (self) "Icky!")))) + +(define New-Worm + (Make-Class 'Worm + #:parents (list Dog) + #:interfaces (list Stinky) + #:methods (hash 'smelly (lambda (self) "Smelly!") 'icky (lambda (self) "Icky!")))) diff --git a/cogs/collections/mvector.scm b/cogs/collections/mvector.scm deleted file mode 100644 index d54129148..000000000 --- a/cogs/collections/mvector.scm +++ /dev/null @@ -1,147 +0,0 @@ -(require-builtin #%private/steel/mvector as private.) - -;; Clean this up -;; Make the built in API just use immutable-vector -(provide vector? - immutable-vector? - mutable-vector? - make-vector - vector - mutable-vector->list) - -(struct StreamIterator - (iter-instance stream-empty-function stream-first-function stream-next-function)) - -;; Call the struct as a function -(struct IntoIterator (iter-object next-function) #:prop:procedure 1) - -; (define ITERATOR-FINISHED 'done) -(define ITERATOR-FINISHED (load-from-module! %-builtin-module-steel/meta '#%iterator-finished)) - -(define (iter-finished? value) - (eq? value ITERATOR-FINISHED)) - -(define (iter-next into-iterator) - (into-iterator (IntoIterator-iter-object into-iterator))) - -;; Generically get the iterator -(define (into-iter obj) - ;; Check if this is a builtin type - if so, delegate to the underlying iterator - (define maybe-builtin-iterator (value->iterator obj)) - - (if maybe-builtin-iterator - (IntoIterator maybe-builtin-iterator iter-next!) - ((#%struct-property-ref obj '#:prop:into-iter) obj))) - -(define (iter-for-each iter func) - - (define next-value (iter-next iter)) - - (if (iter-finished? next-value) - void - (begin - (func next-value) - (iter-for-each iter func)))) - -;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; - -(struct MutableVector (inner) - #:mutable - #:prop:into-iter - (lambda (object) (IntoIterator (MutableVectorIterator object 0) MutableVectorIterator-next)) - #:printer (lambda (this printer-function) - (printer-function "'#(") - (cond - [(mutable-vector-empty? this) void] - [else - (printer-function (mutable-vector-ref this 0)) - (mutable-vector-for-each this - (lambda (elem) - (printer-function " ") - (printer-function elem)) - 1) - (printer-function ")")]))) - -;;@doc -;; Check if the value is an immutable vector -(define immutable-vector? (load-from-module! %-builtin-module-steel/identity 'vector?)) - -;;@doc -;; Check whether the value is a mutable vector -(define mutable-vector? MutableVector?) - -;;@doc -;; Checks whether the value is a vector (mutable or immutable) -(define vector? (lambda (x) (or (immutable-vector? x) (MutableVector? x)))) - -;;@doc -;; Create a vector of length k, optionally initialized with each -;; slot filled with value v. -(define make-vector - (case-lambda - [(k) - (when (< k 0) - (error "make-vector requires a positive integer, found " k)) - - (list->mutable-vector (map (lambda (_) void) (range 0 k)))] - [(k v) - (when (< k 0) - (error "make-vector requires a positive integer, found " k)) - - (list->mutable-vector (map (lambda (_) v) (range 0 k)))])) - -(define (make-mutable-vector) - (MutableVector (private.make-mutable-vector))) - -(define (mutable-vector-ref vector index) - (private.mutable-vector-ref (MutableVector-inner vector) index)) - -(define (mutable-vector-set! vector index value) - (private.mutable-vector-set! (MutableVector-inner vector) index value)) - -(define (mutable-vector-push! vector value) - (private.mutable-vector-push! (MutableVector-inner vector) value)) - -(define (mutable-vector->list vector) - (private.mutable-vector->list (MutableVector-inner vector))) - -(define (mutable-vector-empty? vector) - (private.mutable-vector-empty? (MutableVector-inner vector))) - -(define (mutable-vector-len vector) - (private.mutable-vector-len (MutableVector-inner vector))) - -(define (list->mutable-vector list) - (MutableVector (private.mutable-vector-from-list list))) - -(define (mut-vector . args) - (MutableVector (private.mutable-vector-from-list args))) - -(define vector mut-vector) - -(struct MutableVectorIterator (vec idx) #:mutable) - -(define (MutableVectorIterator-next iter) - - (define offset (MutableVectorIterator-idx iter)) - (define vec (MutableVectorIterator-vec iter)) - - (cond - [(mutable-vector-empty? vec) ITERATOR-FINISHED] - [(>= offset (mutable-vector-len vec)) ITERATOR-FINISHED] - [else - (let ([return-value (mutable-vector-ref vec offset)]) - (set-MutableVectorIterator-idx! iter (+ offset 1)) - return-value)])) - -(define (mutable-vector-for-each vec func offset) - - (let loop ([func func] [iterator (MutableVectorIterator vec offset)]) - - (let ([next (MutableVectorIterator-next iterator)]) - (if (eq? next ITERATOR-FINISHED) - void - - (begin - (func next) - (loop func iterator)))))) diff --git a/crates/steel-core/src/scheme/modules/iterators.scm b/crates/steel-core/src/scheme/modules/iterators.scm index 7602c765f..c7ce2fa30 100644 --- a/crates/steel-core/src/scheme/modules/iterators.scm +++ b/crates/steel-core/src/scheme/modules/iterators.scm @@ -6,6 +6,8 @@ iter-next into-iter iter-for-each + stream-iter-for-each + into-stream-iter ;; For defining generators out of functions directly (for-syntax make-generator!) (for-syntax define/generator)) @@ -13,6 +15,29 @@ (struct StreamIterator (iter-instance stream-empty-function stream-first-function stream-next-function)) +(define (stream-iter-for-each iter func) + + (define obj-stream-empty-function (StreamIterator-stream-empty-function iter)) + (define obj-stream-first-function (StreamIterator-stream-first-function iter)) + (define obj-stream-next-function (StreamIterator-stream-next-function iter)) + + (let loop ([obj (StreamIterator-iter-instance iter)]) + (if (obj-stream-empty-function obj) + void + (begin + (func (obj-stream-first-function obj)) + (loop (obj-stream-next-function obj)))))) + +(define (list-stream-iterator l) + (StreamIterator l empty? car cdr)) + +(define (into-stream-iter obj) + (cond + [(list? obj) (list-stream-iterator obj)] + [(#%private-struct? obj) ((#%struct-property-ref obj '#:prop:into-stream) obj)] + + [else (error "into-stream implementation not found for object" obj)])) + (struct IntoIterator (iter-object next-function) #:prop:procedure 1) ;; Use the builtin "iterator finished" symbol diff --git a/crates/steel-core/src/scheme/print.scm b/crates/steel-core/src/scheme/print.scm index 8979158fc..7e4335bee 100644 --- a/crates/steel-core/src/scheme/print.scm +++ b/crates/steel-core/src/scheme/print.scm @@ -28,7 +28,7 @@ (when (or (symbol? obj) (list? obj)) (simple-display "'")) - (#%print obj cycle-collector)) + (#%top-level-print obj cycle-collector)) (define (displayln . objs) @@ -117,6 +117,10 @@ (define (#%print obj collector) (cond + [(string? obj) + (display "\"") + (simple-display obj) + (display "\"")] [(symbol? obj) (simple-display (symbol->string obj))] [(atom? obj) (simple-display obj)] [(function? obj) (simple-display obj)] diff --git a/crates/steel-core/src/steel_vm/engine.rs b/crates/steel-core/src/steel_vm/engine.rs index 7f162b114..c61864851 100644 --- a/crates/steel-core/src/steel_vm/engine.rs +++ b/crates/steel-core/src/steel_vm/engine.rs @@ -745,7 +745,7 @@ impl Engine { /// Call the print method within the VM pub fn call_printing_method_in_context(&mut self, argument: SteelVal) -> Result { - let function = self.extract_value("println")?; + let function = self.extract_value("displayln")?; self.call_function_with_args(function, vec![argument]) } diff --git a/crates/steel-repl/src/repl.rs b/crates/steel-repl/src/repl.rs index bf0a1162e..047d09669 100644 --- a/crates/steel-repl/src/repl.rs +++ b/crates/steel-repl/src/repl.rs @@ -36,14 +36,19 @@ fn finish_load_or_interrupt(vm: &mut Engine, exprs: String, path: PathBuf) { let res = vm.compile_and_run_raw_program_with_path(exprs.as_str(), path); match res { - Ok(r) => r.iter().for_each(|x| match x { + Ok(r) => r.into_iter().for_each(|x| match x { SteelVal::Void => {} - _ => println!("{} {}", "=>".bright_blue().bold(), x), + SteelVal::StringV(s) => { + println!("{} {:?}", "=>".bright_blue().bold(), s); + } + _ => { + print!("{} ", "=>".bright_blue().bold()); + vm.call_function_by_name_with_args("displayln", vec![x]) + .unwrap(); + } }), Err(e) => { vm.raise_error(e); - // e.emit_result(file_name.as_str(), exprs.as_str()); - // eprintln!("{}", e.to_string().bright_red()); } } } @@ -54,9 +59,16 @@ fn finish_or_interrupt(vm: &mut Engine, line: String, print_time: bool) { let res = vm.compile_and_run_raw_program(&line); match res { - Ok(r) => r.iter().for_each(|x| match x { + Ok(r) => r.into_iter().for_each(|x| match x { SteelVal::Void => {} - _ => println!("{} {}", "=>".bright_blue().bold(), x), + SteelVal::StringV(s) => { + println!("{} {:?}", "=>".bright_blue().bold(), s); + } + _ => { + print!("{} ", "=>".bright_blue().bold()); + vm.call_function_by_name_with_args("displayln", vec![x]) + .unwrap(); + } }), Err(e) => { vm.raise_error(e);