mirror of
https://github.com/kanaka/mal.git
synced 2024-11-10 12:47:45 +03:00
Implement print_readably, completes step 4
This commit is contained in:
parent
dc1a9c479f
commit
e7337b4cd0
@ -1,7 +1,8 @@
|
||||
(load "types")
|
||||
(require "types")
|
||||
(require "printer")
|
||||
|
||||
(defpackage :core
|
||||
(:use :common-lisp :types)
|
||||
(:use :common-lisp :types :printer)
|
||||
(:export :ns))
|
||||
|
||||
(in-package :core)
|
||||
@ -24,9 +25,35 @@
|
||||
(types:make-mal-builtin-fn (lambda (value1 value2)
|
||||
(types:apply-unwrapped-values '/ value1 value2))))
|
||||
|
||||
(cons (types:make-mal-symbol '|list|)
|
||||
(types:make-mal-builtin-fn (lambda (&rest values)
|
||||
(make-mal-list values))))
|
||||
(cons (types:make-mal-symbol '|prn|)
|
||||
(types:make-mal-builtin-fn (lambda (&rest strings)
|
||||
(write-line (format nil
|
||||
"~{~a~^ ~}"
|
||||
(mapcar (lambda (string) (printer:pr-str string t))
|
||||
strings)))
|
||||
(types:make-mal-nil nil))))
|
||||
|
||||
(cons (types:make-mal-symbol '|println|)
|
||||
(types:make-mal-builtin-fn (lambda (&rest strings)
|
||||
(write-line (format nil
|
||||
"~{~a~^ ~}"
|
||||
(mapcar (lambda (string) (printer:pr-str string nil))
|
||||
strings)))
|
||||
(types:make-mal-nil nil))))
|
||||
|
||||
(cons (types:make-mal-symbol '|pr-str|)
|
||||
(types:make-mal-builtin-fn (lambda (&rest strings)
|
||||
(types:make-mal-string (format nil
|
||||
"~{~a~^ ~}"
|
||||
(mapcar (lambda (string) (printer:pr-str string t))
|
||||
strings))))))
|
||||
|
||||
(cons (types:make-mal-symbol '|str|)
|
||||
(types:make-mal-builtin-fn (lambda (&rest strings)
|
||||
(types:make-mal-string (format nil
|
||||
"~{~a~}"
|
||||
(mapcar (lambda (string) (printer:pr-str string nil))
|
||||
strings))))))
|
||||
|
||||
(cons (types:make-mal-symbol '|list?|)
|
||||
(types:make-mal-builtin-fn (lambda (value)
|
||||
|
@ -1,46 +1,57 @@
|
||||
(require "types")
|
||||
(require "utils")
|
||||
|
||||
(defpackage :printer
|
||||
(:use :common-lisp :types)
|
||||
(:use :common-lisp :utils :types)
|
||||
(:export :pr-str))
|
||||
|
||||
(in-package :printer)
|
||||
|
||||
(defun pr-mal-sequence (start-delimiter sequence end-delimiter)
|
||||
(defun pr-mal-sequence (start-delimiter sequence end-delimiter &optional (print-readably t))
|
||||
(concatenate 'string
|
||||
start-delimiter
|
||||
(format nil
|
||||
"~{~A~^ ~}"
|
||||
(map 'list #'pr-str (types:mal-value sequence)))
|
||||
"~{~a~^ ~}"
|
||||
(map 'list (lambda (value)
|
||||
(pr-str value print-readably))
|
||||
(types:mal-value sequence)))
|
||||
end-delimiter))
|
||||
|
||||
(defun pr-mal-hash-map (hash-map)
|
||||
(defun pr-mal-hash-map (hash-map &optional (print-readably t))
|
||||
(let ((hash-map-value (types:mal-value hash-map)))
|
||||
(concatenate 'string
|
||||
"{"
|
||||
(format nil
|
||||
"~{~A~^ ~}"
|
||||
"~{~a~^ ~}"
|
||||
(mapcar (lambda (key-value)
|
||||
(format nil
|
||||
"~a ~a"
|
||||
(pr-str (car key-value))
|
||||
(pr-str (cdr key-value))))
|
||||
(pr-str (car key-value) print-readably)
|
||||
(pr-str (cdr key-value) print-readably)))
|
||||
(loop
|
||||
for key being the hash-keys of hash-map-value
|
||||
collect (cons key (gethash key hash-map-value)))))
|
||||
"}")))
|
||||
|
||||
(defun pr-str (ast)
|
||||
(defun pr-string (ast &optional (print-readably t))
|
||||
(if print-readably
|
||||
(utils:replace-all (prin1-to-string (types:mal-value ast))
|
||||
"
|
||||
"
|
||||
"\\n")
|
||||
(types:mal-value ast)))
|
||||
|
||||
(defun pr-str (ast &optional (print-readably t))
|
||||
(when ast
|
||||
(switch-mal-type ast
|
||||
(types:number (format nil "~d" (types:mal-value ast)))
|
||||
(types:boolean (if (types:mal-value ast) "true" "false"))
|
||||
(types:nil "nil")
|
||||
(types:string (format nil "~s" (types:mal-value ast)))
|
||||
(types:string (pr-string ast print-readably))
|
||||
(types:symbol (format nil "~a" (types:mal-value ast)))
|
||||
(types:keyword (format nil ":~a" (types:mal-value ast)))
|
||||
(types:list (pr-mal-sequence "(" ast ")"))
|
||||
(types:vector (pr-mal-sequence "[" ast "]"))
|
||||
(types:hash-map (pr-mal-hash-map ast))
|
||||
(types:list (pr-mal-sequence "(" ast ")" print-readably))
|
||||
(types:vector (pr-mal-sequence "[" ast "]" print-readably))
|
||||
(types:hash-map (pr-mal-hash-map ast print-readably))
|
||||
(types:fn "#<function>")
|
||||
(types:builtin-fn "#<builtin function>"))))
|
||||
|
@ -1,7 +1,8 @@
|
||||
(require "types")
|
||||
(require "utils")
|
||||
|
||||
(defpackage :reader
|
||||
(:use :regexp :common-lisp :types)
|
||||
(:use :common-lisp :regexp :utils :types)
|
||||
(:export :read-str
|
||||
:eof))
|
||||
|
||||
@ -23,26 +24,14 @@
|
||||
"EOF encountered while reading ~a"
|
||||
(context condition)))))
|
||||
|
||||
(defun replace-all (string part replacement &key (test #'char=))
|
||||
"Returns a new string in which all the occurences of the part
|
||||
is replaced with replacement."
|
||||
(with-output-to-string (out)
|
||||
(loop with part-length = (length part)
|
||||
for old-pos = 0 then (+ pos part-length)
|
||||
for pos = (search part string
|
||||
:start2 old-pos
|
||||
:test test)
|
||||
do (write-string string out
|
||||
:start old-pos
|
||||
:end (or pos (length string)))
|
||||
when pos do (write-string replacement out)
|
||||
while pos)))
|
||||
|
||||
(defun parse-string (token)
|
||||
(if (and (> (length token) 1)
|
||||
(regexp:match *string-re* token))
|
||||
(read-from-string (replace-all token "\\n" "
|
||||
"))
|
||||
(progn
|
||||
(read-from-string (utils:replace-all token
|
||||
"\\n"
|
||||
"
|
||||
")))
|
||||
;; A bit inaccurate
|
||||
(error 'eof
|
||||
:context "string")))
|
||||
|
20
common_lisp/utils.lisp
Normal file
20
common_lisp/utils.lisp
Normal file
@ -0,0 +1,20 @@
|
||||
(defpackage :utils
|
||||
(:use :common-lisp)
|
||||
(:export :replace-all))
|
||||
|
||||
(in-package :utils)
|
||||
|
||||
(defun replace-all (string part replacement &key (test #'char=))
|
||||
"Returns a new string in which all the occurences of the part
|
||||
is replaced with replacement."
|
||||
(with-output-to-string (out)
|
||||
(loop with part-length = (length part)
|
||||
for old-pos = 0 then (+ pos part-length)
|
||||
for pos = (search part string
|
||||
:start2 old-pos
|
||||
:test test)
|
||||
do (write-string string out
|
||||
:start old-pos
|
||||
:end (or pos (length string)))
|
||||
when pos do (write-string replacement out)
|
||||
while pos)))
|
Loading…
Reference in New Issue
Block a user