70 lines
2.0 KiB
OCaml
70 lines
2.0 KiB
OCaml
open Ast;;
|
|
|
|
let add _ vs =
|
|
let rec aux accum = function
|
|
| LCons (a, b) ->
|
|
(match accum, a with
|
|
| LInt x , LInt y -> aux (LInt (x + y)) b
|
|
| LDouble x, LInt y -> aux (LDouble (x +. (float_of_int y))) b
|
|
| LInt x, LDouble y -> aux (LDouble ((float_of_int x) +. y)) b
|
|
| LDouble x, LDouble y -> aux (LDouble (x +. y)) b
|
|
| _ -> invalid_arg "invalid args to +")
|
|
| LNil -> accum
|
|
| _ -> invalid_arg "invalid args to +"
|
|
in aux (LInt 0) vs
|
|
let sub _ vs =
|
|
let rec aux accum = function
|
|
| LNil -> accum
|
|
| LCons (a, b) -> (match accum, a, b with
|
|
| LNil, LDouble x, LNil -> LDouble (-. x)
|
|
| LNil, LInt x, LNil -> LInt (-x)
|
|
| LNil, LDouble _, _
|
|
| LNil, LInt _, _ -> aux a b
|
|
| LInt x, LInt y, _ -> aux (LInt (x - y)) b
|
|
| LInt x, LDouble y, _ -> aux (LDouble ((float_of_int x) -. y)) b
|
|
| LDouble x, LDouble y, _ -> aux (LDouble (x -. y)) b
|
|
| LDouble x, LInt y, _ -> aux (LDouble (x -. (float_of_int y))) b
|
|
| _ -> invalid_arg "invalid argument to -")
|
|
| _ -> invalid_arg "argument to -"
|
|
in aux LNil vs
|
|
|
|
|
|
|
|
let car _ vs =
|
|
match vs with
|
|
| LCons (LCons (a, _), LNil) -> a
|
|
| _ -> raise (Invalid_argument "car: invalid argument")
|
|
|
|
let cdr _ vs =
|
|
match vs with
|
|
| LCons (LCons (_, b), LNil) -> b
|
|
| _ -> raise (Invalid_argument "cdr: invalid argument")
|
|
|
|
let cons _ vs =
|
|
match vs with
|
|
| LCons (a, LCons (b, LNil)) -> LCons (a, b)
|
|
| _ -> invalid_arg "invalid args to cons!"
|
|
|
|
let lisp_list _ vs = vs
|
|
|
|
(* builtin function that updates an existing binding *)
|
|
let lisp_set env = function
|
|
| LCons (LSymbol s, LCons (v, LNil)) ->
|
|
Env.update env s v;
|
|
v
|
|
| _ -> invalid_arg "invalid args to set"
|
|
|
|
let lambda env = function
|
|
| LCons (l, body) ->
|
|
LLambda (env, l, body)
|
|
| _ -> raise (Invalid_argument "invalid args to lambda!")
|
|
|
|
let lambda_macro env = function
|
|
| LCons (l, body) -> LUnnamedMacro (env, l, body)
|
|
| _ -> invalid_arg "invalid args to lambda-macro"
|
|
|
|
|
|
let lisp_not _ = function
|
|
| LCons (LNil, LNil) -> LSymbol "t"
|
|
| _ -> LNil
|