Skip to content

Commit

Permalink
livescript: merge eval_ast into eval
Browse files Browse the repository at this point in the history
  • Loading branch information
asarhaddon committed Oct 10, 2024
1 parent 7e1faf6 commit f9f0006
Show file tree
Hide file tree
Showing 10 changed files with 142 additions and 166 deletions.
15 changes: 3 additions & 12 deletions impls/livescript/env.ls
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,7 @@ export class Env
set: (symbol, ast) ->
@data[symbol] = ast

find: (symbol) ->
if symbol of @data then @
else if @outer? then @outer.find symbol

get: (symbol) ->
result = @try-get symbol
if not result
then throw new Error "'#{symbol}' not found"
else result

try-get: (symbol) ->
env = @find symbol
if env then env.data[symbol]
if symbol of @data
then @data[symbol]
else if @outer? then @outer.find symbol
3 changes: 3 additions & 0 deletions impls/livescript/step2_eval.ls
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ repl_env = do
value: (a, b) -> {type: \int, value: parseInt(a.value / b.value)}

eval_ast = (repl_env, {type, value}: ast) -->

# console.log "EVAL: #{pr_str ast}"

switch type
| \symbol =>
result = repl_env[value]
Expand Down
21 changes: 15 additions & 6 deletions impls/livescript/step3_env.ls
Original file line number Diff line number Diff line change
Expand Up @@ -27,19 +27,28 @@ list-to-pairs = (list) ->
[0 to (list.length - 2) by 2] \
|> map (idx) -> [list[idx], list[idx+1]]

is-thruthy = ({type, value}) ->
type != \const or value not in [\nil \false]


eval_ast = (env, {type, value}: ast) -->

dbgeval = env.get "DEBUG-EVAL"
if dbgeval and is-thruthy dbgeval then console.log "EVAL: #{pr_str ast}"

eval_simple = (env, {type, value}: ast) ->
switch type
| \symbol => env.get value
| \list, \vector => do
or throw new Error "'#{value}' not found"
|> return
| \list =>
# Proceed after this switch
| \vector => do
type: type
value: value |> map eval_ast env
| otherwise => ast
|> return


eval_ast = (env, {type, value}: ast) -->
if type != \list then eval_simple env, ast
else if value.length == 0 then ast
if value.length == 0 then ast
else if value[0].type == \symbol
params = value[1 to]
switch value[0].value
Expand Down
19 changes: 13 additions & 6 deletions impls/livescript/step4_if_fn_do.ls
Original file line number Diff line number Diff line change
Expand Up @@ -15,17 +15,24 @@ fmap-ast = (fn, {type, value}: ast) -->
{type: type, value: fn value}


eval_simple = (env, {type, value}: ast) ->
eval_ast = (env, {type, value}: ast) -->

dbgeval = env.get "DEBUG-EVAL"
if dbgeval and is-thruthy dbgeval then console.log "EVAL: #{pr_str ast}"

switch type
| \symbol => env.get value
| \list, \vector => ast |> fmap-ast map eval_ast env
or throw new Error "'#{value}' not found"
|> return
| \list =>
# Proceed after this switch
| \vector => return (ast |> fmap-ast map eval_ast env)
| \map => ast |> fmap-ast Obj.map eval_ast env
|> return
| otherwise => ast
|> return


eval_ast = (env, {type, value}: ast) -->
if type != \list then eval_simple env, ast
else if value.length == 0 then ast
if value.length == 0 then ast
else if value[0].type == \symbol
params = value[1 to]
switch value[0].value
Expand Down
23 changes: 15 additions & 8 deletions impls/livescript/step5_tco.ls
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,27 @@ fmap-ast = (fn, {type, value}: ast) -->
{type: type, value: fn value}


eval_simple = (env, {type, value}: ast) ->
eval_ast = (env, {type, value}: ast) -->
loop

dbgeval = env.get "DEBUG-EVAL"
if dbgeval and is-thruthy dbgeval then console.log "EVAL: #{pr_str ast}"

switch type
| \symbol => env.get value
| \list, \vector => ast |> fmap-ast map eval_ast env
or throw new Error "'#{value}' not found"
|> return
| \list =>
# Proceed after this switch
| \vector => return (ast |> fmap-ast map eval_ast env)
| \map => ast |> fmap-ast Obj.map eval_ast env
|> return
| otherwise => ast
|> return


eval_ast = (env, {type, value}: ast) -->
loop
if type != \list
return eval_simple env, ast
else if value.length == 0
if value.length == 0
return ast
else

result = if value[0].type == \symbol
params = value[1 to]
Expand Down
23 changes: 15 additions & 8 deletions impls/livescript/step6_file.ls
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,27 @@ fmap-ast = (fn, {type, value}: ast) -->
{type: type, value: fn value}


eval_simple = (env, {type, value}: ast) ->
eval_ast = (env, {type, value}: ast) -->
loop

dbgeval = env.get "DEBUG-EVAL"
if dbgeval and is-thruthy dbgeval then console.log "EVAL: #{pr_str ast}"

switch type
| \symbol => env.get value
| \list, \vector => ast |> fmap-ast map eval_ast env
or throw new Error "'#{value}' not found"
|> return
| \list =>
# Proceed after this switch
| \vector => return (ast |> fmap-ast map eval_ast env)
| \map => ast |> fmap-ast Obj.map eval_ast env
|> return
| otherwise => ast
|> return


eval_ast = (env, {type, value}: ast) -->
loop
if type != \list
return eval_simple env, ast
else if value.length == 0
if value.length == 0
return ast
else

result = if value[0].type == \symbol
params = value[1 to]
Expand Down
24 changes: 15 additions & 9 deletions impls/livescript/step7_quote.ls
Original file line number Diff line number Diff line change
Expand Up @@ -28,20 +28,27 @@ make-call = (name, params) -> make-list [make-symbol name] ++ params
is-symbol = (ast, name) -> ast.type == \symbol and ast.value == name


eval_simple = (env, {type, value}: ast) ->
eval_ast = (env, {type, value}: ast) -->
loop

dbgeval = env.get "DEBUG-EVAL"
if dbgeval and is-thruthy dbgeval then console.log "EVAL: #{pr_str ast}"

switch type
| \symbol => env.get value
| \list, \vector => ast |> fmap-ast map eval_ast env
or throw new Error "'#{value}' not found"
|> return
| \list =>
# Proceed after this switch
| \vector => return (ast |> fmap-ast map eval_ast env)
| \map => ast |> fmap-ast Obj.map eval_ast env
|> return
| otherwise => ast
|> return


eval_ast = (env, {type, value}: ast) -->
loop
if type != \list
return eval_simple env, ast
else if value.length == 0
if value.length == 0
return ast
else

result = if value[0].type == \symbol
params = value[1 to]
Expand All @@ -52,7 +59,6 @@ eval_ast = (env, {type, value}: ast) -->
| 'if' => eval_if env, params
| 'fn*' => eval_fn env, params
| 'quote' => eval_quote env, params
| 'quasiquoteexpand' => eval_quasiquoteexpand params
| 'quasiquote' => eval_quasiquote env, params
| otherwise => eval_apply env, value
else
Expand Down
60 changes: 21 additions & 39 deletions impls/livescript/step8_macros.ls
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,27 @@ make-call = (name, params) -> make-list [make-symbol name] ++ params
is-symbol = (ast, name) -> ast.type == \symbol and ast.value == name


eval_simple = (env, {type, value}: ast) ->
eval_ast = (env, {type, value}: ast) -->
loop

dbgeval = env.get "DEBUG-EVAL"
if dbgeval and is-thruthy dbgeval then console.log "EVAL: #{pr_str ast}"

switch type
| \symbol => env.get value
| \list, \vector => ast |> fmap-ast map eval_ast env
or throw new Error "'#{value}' not found"
|> return
| \list =>
# Proceed after this switch
| \vector => return (ast |> fmap-ast map eval_ast env)
| \map => ast |> fmap-ast Obj.map eval_ast env
|> return
| otherwise => ast
|> return


eval_ast = (env, ast) -->
loop
if ast.type != \list
return eval_simple env, ast

ast = macroexpand env, ast
if ast.type != \list
return eval_simple env, ast
else if ast.value.length == 0
if value.length == 0
return ast
else

result = if ast.value[0].type == \symbol
params = ast.value[1 to]
Expand All @@ -56,10 +59,8 @@ eval_ast = (env, ast) -->
| 'if' => eval_if env, params
| 'fn*' => eval_fn env, params
| 'quote' => eval_quote env, params
| 'quasiquoteexpand' => eval_quasiquoteexpand params
| 'quasiquote' => eval_quasiquote env, params
| 'defmacro!' => eval_defmacro env, params
| 'macroexpand' => eval_macroexpand env, params
| otherwise => eval_apply env, ast.value
else
eval_apply env, ast.value
Expand Down Expand Up @@ -198,10 +199,15 @@ eval_fn = (env, params) ->


eval_apply = (env, list) ->
[fn, ...args] = list |> map eval_ast env
[first, ...raw_args] = list
fn = eval_ast env first
if fn.type != \function
runtime-error "#{fn.value} is not a function, got a #{fn.type}"

if fn.is_macro
return defer-tco env, unpack-tco fn.value.apply env, raw_args

args = map eval_ast env, raw_args
fn.value.apply env, args


Expand Down Expand Up @@ -280,30 +286,6 @@ eval_defmacro = (env, params) ->
env.set name.value, macro_fn


get-macro-fn = (env, ast) ->
if ast.type == \list and
ast.value.length != 0 and
ast.value[0].type == \symbol
fn = env.try-get ast.value[0].value
if fn and fn.type == \function and fn.is_macro
then fn


macroexpand = (env, ast) ->
loop # until ast is not a macro function call.
macro_fn = get-macro-fn env, ast
if not macro_fn then return ast
ast = unpack-tco <| macro_fn.value.apply env, ast.value[1 to]


eval_macroexpand = (env, params) ->
if params.length != 1
runtime-error "'macroexpand' expected 1 parameter,
got #{params.length}"

macroexpand env, params[0]


repl_env = new Env
for symbol, value of ns
repl_env.set symbol, value
Expand Down
Loading

0 comments on commit f9f0006

Please sign in to comment.