-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Builtins package is now part of eval package
- Loading branch information
1 parent
47d452d
commit a99b610
Showing
15 changed files
with
274 additions
and
229 deletions.
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
package eval | ||
|
||
import ( | ||
"github.com/brendantang/naiveconcat/data" | ||
) | ||
|
||
// not pops a boolean and pushes its negation. | ||
func not(d *data.Dictionary, s *data.Stack) error { | ||
b, err := s.Pop() | ||
if err != nil { | ||
return err | ||
} | ||
if b.Type != data.Boolean { | ||
return data.TypeError(b, data.Boolean) | ||
} | ||
s.Push(data.NewBoolean(!b.Bool)) | ||
return nil | ||
} | ||
|
||
// or pops two booleans and pushes TRUE if either of them is TRUE, FALSE | ||
// otherwise. | ||
func or(d *data.Dictionary, s *data.Stack) error { | ||
a, err := s.Pop() | ||
if err != nil { | ||
return err | ||
} | ||
if a.Type != data.Boolean { | ||
return data.TypeError(a, data.Boolean) | ||
} | ||
b, err := s.Pop() | ||
if err != nil { | ||
return err | ||
} | ||
if b.Type != data.Boolean { | ||
return data.TypeError(b, data.Boolean) | ||
} | ||
s.Push(data.NewBoolean(b.Bool || a.Bool)) | ||
return nil | ||
} | ||
|
||
// and pops two booleans and pushes TRUE if both of them are TRUE, FALSE | ||
// otherwise. | ||
func and(d *data.Dictionary, s *data.Stack) error { | ||
a, err := s.Pop() | ||
if err != nil { | ||
return err | ||
} | ||
if a.Type != data.Boolean { | ||
return data.TypeError(a, data.Boolean) | ||
} | ||
b, err := s.Pop() | ||
if err != nil { | ||
return err | ||
} | ||
if b.Type != data.Boolean { | ||
return data.TypeError(b, data.Boolean) | ||
} | ||
s.Push(data.NewBoolean(b.Bool && a.Bool)) | ||
return nil | ||
} | ||
|
||
// then pops a predicate and a value. If the predicate is TRUE, push the value. | ||
// Otherwise discard it. | ||
func then(d *data.Dictionary, s *data.Stack) error { | ||
predicate, err := s.Pop() | ||
if err != nil { | ||
return err | ||
} | ||
if predicate.Type != data.Boolean { | ||
return data.TypeError(predicate, data.Boolean) | ||
} | ||
consequent, err := s.Pop() | ||
if err != nil { | ||
return err | ||
} | ||
if predicate.Bool { | ||
err := Eval(consequent, d, s) | ||
if err != nil { | ||
return err | ||
} | ||
} | ||
return nil | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
package eval | ||
|
||
import ( | ||
"github.com/brendantang/naiveconcat/data" | ||
) | ||
|
||
// StdDict returns a data.Dictionary with bindings for the standard primitive words. | ||
func StdDict() *data.Dictionary { | ||
return data.NewDictionary( | ||
nil, | ||
map[string]data.Value{ | ||
// IO | ||
"say": data.NewProc(say), // pop a value and print it | ||
"stack": data.NewProc(showStack), // print the whole stack | ||
|
||
// MATH | ||
"+": data.NewProc(add), // pop two numbers and push their sum | ||
"-": data.NewProc(subtract), // pop a, pop b, push b - a | ||
"*": data.NewProc(multiply), // pop two numbers and push their product | ||
"/": data.NewProc(divide), // pop a, pop b, push b divided by a | ||
"=": data.NewProc(equal), // pop two numbers and push whether they're equal | ||
|
||
// BOOLEANS | ||
"true": data.NewBoolean(true), // TRUE literal | ||
"false": data.NewBoolean(false), // FALSE literal | ||
"not": data.NewProc(not), // pop a boolean, push its negation | ||
"or": data.NewProc(or), // pop two bools, push a bool saying whether either is true | ||
"and": data.NewProc(and), // pop two bools, push a bool saying whether both are true | ||
"then": data.NewProc(then), // pop a bool and x, evaluate x if the bool is TRUE | ||
|
||
// QUOTATIONS | ||
"length": data.NewProc(length), // push length of the quotation on top of the stack | ||
"lop": data.NewProc(lop), // pop quotation { a b c ... }, push { b c ... }, push a | ||
|
||
// DICTIONARY MANIPULATION | ||
"let": data.NewProc(let), // pop a string and a value, make a word named by string, defined by value | ||
"define": data.NewProc(define), // pop a string and x. make a word named by string, defined by proc that evals to x. | ||
|
||
// STACK MANIPULATION | ||
"dup": data.NewProc(dup), // pop a, push a, push a | ||
"drop": data.NewProc(drop), // pop a, discard it | ||
"apply": data.NewProc(apply), // pop x. if x is a quotation, eval each item. otherwise, eval x. | ||
"lambda": data.NewProc(lambda), // pop x, push a proc that evals to x. | ||
}, | ||
) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
package eval | ||
|
||
import ( | ||
"github.com/brendantang/naiveconcat/data" | ||
) | ||
|
||
// let pops a string and the next value, then saves a word named for that string | ||
// which evaluates to that value. | ||
func let(d *data.Dictionary, s *data.Stack) error { | ||
wordName, err := s.Pop() | ||
if err != nil { | ||
return err | ||
} | ||
if wordName.Type != data.String { | ||
return data.TypeError(wordName, data.String) | ||
} | ||
definition, err := s.Pop() | ||
if err != nil { | ||
return err | ||
} | ||
|
||
d.Set(wordName.Str, definition) | ||
return nil | ||
} | ||
|
||
// define pops a string and the next value, then saves a word named for that string which evaluates to a procedure that applies that value. | ||
func define(d *data.Dictionary, s *data.Stack) error { | ||
|
||
wordName, err := s.Pop() | ||
if err != nil { | ||
return err | ||
} | ||
if wordName.Type != data.String { | ||
return data.TypeError(wordName, data.String) | ||
} | ||
definition, err := s.Pop() | ||
if err != nil { | ||
return err | ||
} | ||
proc := data.NewProc( | ||
func(d *data.Dictionary, s *data.Stack) error { | ||
s.Push(definition) | ||
return apply(d, s) | ||
}, | ||
) | ||
d.Set(wordName.Str, proc) | ||
|
||
return nil | ||
} |
Oops, something went wrong.