Skip to content

Commit

Permalink
Fix empty list eval in step2 for most languages.
Browse files Browse the repository at this point in the history
I think the only remaining ones are ada, elisp, factor, and rust.
  • Loading branch information
kanaka committed Apr 2, 2016
1 parent a26c256 commit efa2dae
Show file tree
Hide file tree
Showing 36 changed files with 79 additions and 18 deletions.
1 change: 1 addition & 0 deletions bash/step2_eval.sh
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ EVAL () {
EVAL_AST "${ast}" "${env}"
return
fi
_empty? "${ast}" && r="${ast}" && return

# apply list
EVAL_AST "${ast}" "${env}"
Expand Down
6 changes: 4 additions & 2 deletions clojure/src/step2_eval.clj
Original file line number Diff line number Diff line change
Expand Up @@ -32,11 +32,13 @@
(eval-ast ast env)

;; apply list
;; indented to match later steps
;; indented to match later steps
(if (empty? ast)
ast
(let [el (eval-ast ast env)
f (first el)
args (rest el)]
(apply f args))))
(apply f args)))))

;; print
(defn PRINT [exp] (pr-str exp))
Expand Down
1 change: 1 addition & 0 deletions coffee/step2_eval.coffee
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ eval_ast = (ast, env) ->
EVAL = (ast, env) ->
#console.log "EVAL:", printer._pr_str ast
if !types._list_Q ast then return eval_ast ast, env
if ast.length == 0 then return ast

# apply list
[f, args...] = eval_ast ast, env
Expand Down
2 changes: 1 addition & 1 deletion crystal/step2_eval.cr
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ module Mal
def eval(t, env)
Mal::Type.new case ast = t.unwrap
when Mal::List
eval_error "empty list" if ast.empty?
return gen_type Mal::List if ast.empty?

f = eval_ast(ast.first, env)
ast.shift(1)
Expand Down
4 changes: 4 additions & 0 deletions d/step2_eval.d
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,10 @@ MalType EVAL(MalType ast, Env env)
{
return eval_ast(ast, env);
}
if ((cast(MalList) ast).elements.length == 0)
{
return ast;
}

auto el = verify_cast!MalList(eval_ast(ast, env));
auto fobj = verify_cast!MalBuiltinFunc(el.elements[0]);
Expand Down
1 change: 1 addition & 0 deletions elixir/lib/mix/tasks/step2_eval.ex
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ defmodule Mix.Tasks.Step2Eval do
Mal.Reader.read_str(input)
end

defp eval({:list, [], _} = empty_ast, env), do: empty_ast
defp eval({:list, ast, meta}, env), do: eval_list(ast, env, meta)
defp eval(ast, env), do: eval_ast(ast, env)

Expand Down
1 change: 1 addition & 0 deletions es6/step2_eval.js
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ const eval_ast = (ast, env) => {

const EVAL = (ast, env) => {
if (!_list_Q(ast)) { return eval_ast(ast, env) }
if (ast.length === 0) { return ast }

const [f, ...args] = eval_ast(ast, env)
return f(...args)
Expand Down
8 changes: 6 additions & 2 deletions forth/step2_eval.fs
Original file line number Diff line number Diff line change
Expand Up @@ -77,8 +77,12 @@ drop

MalList
extend mal-eval { env list -- val }
env list MalList/start @ @ eval
env list rot eval-invoke ;;
list MalList/count @ 0= if
list
else
env list MalList/start @ @ eval
env list rot eval-invoke
endif ;;
drop

MalVector
Expand Down
1 change: 1 addition & 0 deletions fsharp/step2_eval.fs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ module REPL
| node -> node

and eval env = function
| List(_, []) as emptyList -> emptyList
| List(_, _) as node ->
let resolved = node |> eval_ast env
match resolved with
Expand Down
4 changes: 2 additions & 2 deletions go/src/core/core.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ func empty_Q(a []MalType) (MalType, error) {
case nil:
return true, nil
default:
return nil, errors.New("Count called on non-sequence")
return nil, errors.New("empty? called on non-sequence")
}
}

Expand All @@ -250,7 +250,7 @@ func count(a []MalType) (MalType, error) {
case nil:
return 0, nil
default:
return nil, errors.New("Count called on non-sequence")
return nil, errors.New("count called on non-sequence")
}
}

Expand Down
4 changes: 4 additions & 0 deletions go/src/step2_eval/step2_eval.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,10 @@ func EVAL(ast MalType, env map[string]MalType) (MalType, error) {
return eval_ast(ast, env)
}

if len(ast.(List).Val) == 0 {
return ast, nil
}

// apply list
el, e := eval_ast(ast, env)
if e != nil {
Expand Down
1 change: 1 addition & 0 deletions groovy/step2_eval.groovy
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ eval_ast = { ast, env ->

EVAL = { ast, env ->
if (! types.list_Q(ast)) return eval_ast(ast, env)
if (ast.size() == 0) return ast

def el = eval_ast(ast, env)
def (f, args) = [el[0], el[1..-1]]
Expand Down
1 change: 1 addition & 0 deletions guile/step2_eval.scm
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@

(define (EVAL ast env)
(match ast
(() ast)
((? list?) (eval_func ast env))
(else (eval_ast ast env))))

Expand Down
2 changes: 2 additions & 0 deletions haskell/step2_eval.hs
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ eval_ast ast@(MalHashMap lst m) env = do
eval_ast ast env = return ast

apply_ast :: MalVal -> (Map.Map String MalVal) -> IOThrows MalVal
apply_ast ast@(MalList [] _) env = do
return ast
apply_ast ast@(MalList _ _) env = do
el <- eval_ast ast env
case el of
Expand Down
3 changes: 3 additions & 0 deletions haxe/Step2_eval.hx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ class Step2_eval {
if (!list_Q(ast)) { return eval_ast(ast, env); }

// apply
var alst = switch (ast) { case MalList(lst): lst; case _: []; }
if (alst.length == 0) { return ast; }

var el = eval_ast(ast, env);
var lst = switch (el) { case MalList(lst): lst; case _: []; }
var a0 = lst[0], args = lst.slice(1);
Expand Down
1 change: 1 addition & 0 deletions io/step2_eval.io
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ eval_ast := method(ast, env,

EVAL := method(ast, env,
if(ast type != "MalList", return(eval_ast(ast, env)))
if(ast isEmpty, return ast)
el := eval_ast(ast, env)
f := el at(0)
args := el rest
Expand Down
3 changes: 3 additions & 0 deletions js/step2_eval.js
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@ function _EVAL(ast, env) {
if (!types._list_Q(ast)) {
return eval_ast(ast, env);
}
if (ast.length === 0) {
return ast;
}

// apply list
var el = eval_ast(ast, env), f = el[0];
Expand Down
1 change: 1 addition & 0 deletions julia/step2_eval.jl
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ end

function EVAL(ast, env)
if !isa(ast, Array) return eval_ast(ast, env) end
if isempty(ast) return ast end

# apply
el = eval_ast(ast, env)
Expand Down
2 changes: 1 addition & 1 deletion kotlin/src/mal/step2_eval.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package mal
fun read(input: String?): MalType = read_str(input)

fun eval(ast: MalType, env: Map<String, MalType>): MalType =
if (ast is MalList) {
if (ast is MalList && ast.count() > 0) {
val evaluated = eval_ast(ast, env) as ISeq
if (evaluated.first() !is MalFunction) throw MalException("cannot execute non-function")
(evaluated.first() as MalFunction).apply(evaluated.rest())
Expand Down
1 change: 1 addition & 0 deletions lua/step2_eval.lua
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ end
function EVAL(ast, env)
--print("EVAL: "..printer._pr_str(ast,true))
if not types._list_Q(ast) then return eval_ast(ast, env) end
if #ast == 0 then return ast end
local args = eval_ast(ast, env)
local f = table.remove(args, 1)
return f(unpack(args))
Expand Down
4 changes: 3 additions & 1 deletion make/step2_eval.mk
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ define EVAL
$(strip $(if $(__ERROR),,\
$(and $(EVAL_DEBUG),$(info EVAL: $(call _pr_str,$(1))))\
$(if $(call _list?,$(1)),\
$(strip $(call EVAL_INVOKE,$(1),$(2))),\
$(if $(call _EQ,0,$(call _count,$(1))),\
$(1),\
$(strip $(call EVAL_INVOKE,$(1),$(2)))),\
$(call EVAL_AST,$(1),$(2)))))
endef

Expand Down
10 changes: 6 additions & 4 deletions mal/step2_eval.mal
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,12 @@
(eval-ast ast env)

;; apply list
(let* [el (eval-ast ast env)
f (first el)
args (rest el)]
(apply f args))))))
(if (empty? ast)
ast
(let* [el (eval-ast ast env)
f (first el)
args (rest el)]
(apply f args)))))))


;; print
Expand Down
10 changes: 6 additions & 4 deletions miniMAL/step2_eval.json
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,12 @@
["def", "EVAL", ["fn", ["ast", "env"],
["if", ["not", ["list?", "ast"]],
["eval-ast", "ast", "env"],
["let", ["el", ["eval-ast", "ast", "env"],
"f", ["first", "el"],
"args", ["rest", "el"]],
["apply", "f", "args"]]]]],
["if", ["empty?", "ast"],
"ast",
["let", ["el", ["eval-ast", "ast", "env"],
"f", ["first", "el"],
"args", ["rest", "el"]],
["apply", "f", "args"]]]]]],

["def", "PRINT", ["fn", ["exp"],
["pr-str", "exp", true]]],
Expand Down
1 change: 1 addition & 0 deletions nim/step2_eval.nim
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ proc eval_ast(ast: MalType, env: Table[string, MalType]): MalType =
proc eval(ast: MalType, env: Table[string, MalType]): MalType =
case ast.kind
of List:
if ast.list.len == 0: return ast
let el = ast.eval_ast(env)
el.list[0].fun(el.list[1 .. ^1])
else:
Expand Down
1 change: 1 addition & 0 deletions perl/step2_eval.pl
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ sub EVAL {
}

# apply list
if (scalar(@{$ast->{val}}) == 0) { return $ast; }
my $el = eval_ast($ast, $env);
my $f = $el->nth(0);
return &{ $f }($el->rest());
Expand Down
3 changes: 3 additions & 0 deletions php/step2_eval.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ function MAL_EVAL($ast, $env) {
if (!_list_Q($ast)) {
return eval_ast($ast, $env);
}
if ($ast->count() === 0) {
return $ast;
}

// apply list
$el = eval_ast($ast, $env);
Expand Down
1 change: 1 addition & 0 deletions process/guide.md
Original file line number Diff line number Diff line change
Expand Up @@ -515,6 +515,7 @@ repl_env = {'+': lambda a,b: a+b,
* Modify `EVAL` to check if the first parameter `ast` is a list.
* `ast` is not a list: then return the result of calling `eval_ast`
on it.
* `ast` is a empty list: return ast unchanged.
* `ast` is a list: call `eval_ast` to get a new evaluated list. Take
the first item of the evaluated list and call it as function using
the rest of the evaluated list as its arguments.
Expand Down
Binary file modified ps/step2_eval.ps
Binary file not shown.
1 change: 1 addition & 0 deletions python/step2_eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ def EVAL(ast, env):
return eval_ast(ast, env)

# apply list
if len(ast) == 0: return ast
el = eval_ast(ast, env)
f = el[0]
return f(*el[1:])
Expand Down
3 changes: 3 additions & 0 deletions r/step2_eval.r
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ EVAL <- function(ast, env) {
}

# apply list
if (length(ast) == 0) {
return(ast)
}
el <- eval_ast(ast, env)
f <- el[[1]]
return(do.call(f,el[-1]))
Expand Down
2 changes: 1 addition & 1 deletion racket/step2_eval.rkt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
[else ast]))

(define (EVAL ast env)
(if (not (list? ast))
(if (or (not (list? ast)) (empty? ast))
(eval-ast ast env)

(let* ([el (eval-ast ast env)]
Expand Down
1 change: 1 addition & 0 deletions rpython/step2_eval.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ def EVAL(ast, env):
return eval_ast(ast, env)

# apply list
if len(ast) == 0: return ast
el = eval_ast(ast, env)
f = el.values[0]
if isinstance(f, MalFunc):
Expand Down
3 changes: 3 additions & 0 deletions ruby/step2_eval.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,9 @@ def EVAL(ast, env)
if not ast.is_a? List
return eval_ast(ast, env)
end
if ast.empty?
return ast
end

# apply list
el = eval_ast(ast, env)
Expand Down
2 changes: 2 additions & 0 deletions scala/step2_eval.scala
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ object step2_eval {
return eval_ast(ast, env)

// apply list
if (ast.asInstanceOf[MalList].value.length == 0)
return ast
eval_ast(ast, env).asInstanceOf[MalList].value match {
case f :: el => {
var fn: List[Any] => Any = null
Expand Down
4 changes: 4 additions & 0 deletions tcl/step2_eval.tcl
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,10 @@ proc EVAL {ast env} {
if {![list_q $ast]} {
return [eval_ast $ast $env]
}
set a0 [lindex [obj_val $ast] 0]
if {$a0 == ""} {
return $ast
}
set lst_obj [eval_ast $ast $env]
set lst [obj_val $lst_obj]
set f [lindex $lst 0]
Expand Down
3 changes: 3 additions & 0 deletions vimscript/step2_eval.vim
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ function EVAL(ast, env)
if !ListQ(a:ast)
return EvalAst(a:ast, a:env)
end
if EmptyQ(a:ast)
return a:ast
endif

" apply list
let el = EvalAst(a:ast, a:env)
Expand Down

0 comments on commit efa2dae

Please sign in to comment.