(cond
((null arg) "")
((integerp arg) (integer-to-string arg))
+ ((floatp arg) (float-to-string arg))
((stringp arg) arg)
(t (error "Unknown argument."))))
args))
(defun literal (sexp &optional recursive)
(cond
((integerp sexp) (integer-to-string sexp))
+ ((floatp sexp) (float-to-string sexp))
((stringp sexp) (code "\"" (escape-string sexp) "\""))
((symbolp sexp)
(or (cdr (assoc sexp *literal-symbols*))
(fargs '())
(prelude ""))
(dolist (x args)
- (if (numberp x)
- (push (integer-to-string x) fargs)
- (let ((v (code "x" (incf counter))))
- (push v fargs)
- (concatf prelude
- (code "var " v " = " (ls-compile x) ";" *newline*
- "if (typeof " v " !== 'number') throw 'Not a number!';"
- *newline*)))))
+ (cond
+ ((floatp x) (push (float-to-string x) fargs))
+ ((numberp x) (push (integer-to-string x) fargs))
+ (t (let ((v (code "x" (incf counter))))
+ (push v fargs)
+ (concatf prelude
+ (code "var " v " = " (ls-compile x) ";" *newline*
+ "if (typeof " v " !== 'number') throw 'Not a number!';"
+ *newline*))))))
(js!selfcall prelude (funcall function (reverse fargs)))))
(type-check (("x" "number" x))
"Math.floor(x)"))
+(define-builtin expt (x y)
+ (type-check (("x" "number" x)
+ ("y" "number" y))
+ "Math.pow(x, y)"))
+
+(define-builtin float-to-string (x)
+ (type-check (("x" "number" x))
+ "x.toString()"))
+
(define-builtin cons (x y)
(code "({car: " x ", cdr: " y "})"))
(intern name package)
(find-symbol name package))))
+(defun read-float (string)
+ (block nil
+ (let ((sign 1)
+ (integer-part nil)
+ (fractional-part nil)
+ (number 0)
+ (divisor 1)
+ (exponent-sign 1)
+ (exponent 0)
+ (size (length string))
+ (index 0))
+ (when (zerop size) (return))
+ ;; Optional sign
+ (case (char string index)
+ (#\+ (incf index))
+ (#\- (setq sign -1)
+ (incf index)))
+ (unless (< index size) (return))
+ ;; Optional integer part
+ (let ((value (digit-char-p (char string index))))
+ (when value
+ (setq integer-part t)
+ (while (and (< index size)
+ (setq value (digit-char-p (char string index))))
+ (setq number (+ (* number 10) value))
+ (incf index))))
+ (unless (< index size) (return))
+ ;; Decimal point is mandatory if there's no integer part
+ (unless (or integer-part (char= #\. (char string index))) (return))
+ ;; Optional fractional part
+ (when (char= #\. (char string index))
+ (incf index)
+ (unless (< index size) (return))
+ (let ((value (digit-char-p (char string index))))
+ (when value
+ (setq fractional-part t)
+ (while (and (< index size)
+ (setq value (digit-char-p (char string index))))
+ (setq number (+ (* number 10) value))
+ (setq divisor (* divisor 10))
+ (incf index)))))
+ ;; Either left or right part of the dot must be present
+ (unless (or integer-part fractional-part) (return))
+ ;; Exponent is mandatory if there is no fractional part
+ (when (and (= index size) (not fractional-part)) (return))
+ ;; Optional exponent part
+ (when (< index size)
+ ;; Exponent-marker
+ (unless (member (char-upcase (char string index))
+ '(#\E #\S #\F #\D \#L))
+ (return))
+ (incf index)
+ (unless (< index size) (return))
+ ;; Optional exponent sign
+ (case (char string index)
+ (#\+ (incf index))
+ (#\- (setq exponent-sign -1)
+ (incf index)))
+ (unless (< index size) (return))
+ ;; Exponent digits
+ (let ((value (digit-char-p (char string index))))
+ (unless value (return))
+ (while (and (< index size)
+ (setq value (digit-char-p (char string index))))
+ (setq exponent (+ (* exponent 10) value))
+ (incf index))))
+ (unless (= index size) (return))
+ ;; Everything went ok, we have a float
+ (/ (* sign (expt 10 (* exponent-sign exponent)) number) divisor))))
+
(defun !parse-integer (string junk-allow)
(block nil
(t
(let ((string (read-until stream #'terminalp)))
(or (values (!parse-integer string nil))
+ (read-float string)
(read-symbol string)))))))
(defun ls-read (stream &optional (eof-error-p t) eof-value)
copy-list decf declaim defconstant define-setf-expander
define-symbol-macro defmacro defparameter defun defvar
digit-char digit-char-p disassemble do do* documentation
- dolist dotimes ecase eq eql equal error eval every export
+ dolist dotimes ecase eq eql equal error eval every export expt
fdefinition find-package find-symbol first flet fourth fset
funcall function functionp gensym get-setf-expansion
get-universal-time go identity if in-package incf integerp