Type check
This commit is contained in:
parent
8f5b16878f
commit
0cd6040a1f
7 changed files with 625 additions and 256 deletions
114
parse.go
114
parse.go
|
|
@ -8,56 +8,12 @@ import (
|
|||
|
||||
var (
|
||||
noMatch = errors.New("no match")
|
||||
zero = &Value[int]{0}
|
||||
)
|
||||
|
||||
type Function func([]Expression) (Expression, error)
|
||||
|
||||
type Expression interface {
|
||||
Step() (Expression, error)
|
||||
Replace(Id, Expression)
|
||||
}
|
||||
|
||||
type List struct {
|
||||
els []Expression
|
||||
}
|
||||
|
||||
type Value[T interface{ int | float64 | Function }] struct {
|
||||
value T
|
||||
// rng Range
|
||||
}
|
||||
|
||||
type Quoted struct {
|
||||
expr Expression
|
||||
}
|
||||
|
||||
type Declaration struct {
|
||||
variables []*Symbol
|
||||
body []Expression
|
||||
}
|
||||
|
||||
type Lambda struct {
|
||||
args []*Symbol
|
||||
body []Expression
|
||||
}
|
||||
|
||||
type Symbol struct {
|
||||
id *Identifier
|
||||
expr Expression
|
||||
}
|
||||
|
||||
// type Progn struct {
|
||||
// *List
|
||||
// }
|
||||
|
||||
func (v Value[T]) String() string {
|
||||
return fmt.Sprint(v.value)
|
||||
}
|
||||
|
||||
func (v Quoted) String() string {
|
||||
return fmt.Sprintf("'%s", v.expr)
|
||||
}
|
||||
|
||||
func (v List) String() string {
|
||||
var s []string
|
||||
for _, e := range v.els {
|
||||
|
|
@ -68,7 +24,7 @@ func (v List) String() string {
|
|||
|
||||
func (v Lambda) String() string {
|
||||
var args List
|
||||
for _, arg := range v.args {
|
||||
for _, arg := range v.params {
|
||||
args.els = append(args.els, arg)
|
||||
}
|
||||
var s []string
|
||||
|
|
@ -78,10 +34,6 @@ func (v Lambda) String() string {
|
|||
return fmt.Sprintf("(lambda %v %v)", &args, strings.Join(s, " "))
|
||||
}
|
||||
|
||||
func (v Function) String() string {
|
||||
return "(lambda (..) (..))"
|
||||
}
|
||||
|
||||
func (t Symbol) String() string {
|
||||
return fmt.Sprintf("%v", t.id.value)
|
||||
}
|
||||
|
|
@ -109,6 +61,17 @@ func parseSymbol(in *Input) (Expression, error) {
|
|||
return nil, noMatch
|
||||
}
|
||||
switch x := l.(type) {
|
||||
case *Token:
|
||||
switch {
|
||||
case x.Equals(TrueTok):
|
||||
v := BoolValue(true)
|
||||
return &v, nil
|
||||
case x.Equals(NilTok):
|
||||
v := BoolValue(false)
|
||||
return &v, nil
|
||||
default:
|
||||
return nil, noMatch
|
||||
}
|
||||
case *Identifier:
|
||||
return &Symbol{id: x}, nil
|
||||
default:
|
||||
|
|
@ -122,10 +85,12 @@ func parseValue(in *Input) (Expression, error) {
|
|||
return nil, noMatch
|
||||
}
|
||||
switch x := l.(type) {
|
||||
case *Int:
|
||||
return &Value[int]{x.value}, nil
|
||||
case *Float:
|
||||
return &Value[float64]{x.value}, nil
|
||||
case *IntToken:
|
||||
r := IntValue(x.value)
|
||||
return &r, nil
|
||||
case *FloatToken:
|
||||
r := FloatValue(x.value)
|
||||
return &r, nil
|
||||
default:
|
||||
return nil, noMatch
|
||||
}
|
||||
|
|
@ -172,6 +137,10 @@ func parseLet(in *Input) (Expression, error) {
|
|||
return nil, fmt.Errorf("unmatched parenthesis starting at %s", openingParens.Position())
|
||||
}
|
||||
decl := in.Take(idx)
|
||||
_, ok = in.Pop()
|
||||
if !ok {
|
||||
return nil, noMatch
|
||||
}
|
||||
tok, ok := decl.Pop()
|
||||
if !ok {
|
||||
return nil, noMatch
|
||||
|
|
@ -254,7 +223,43 @@ func parseLambda(in *Input) (Expression, error) {
|
|||
if !ok {
|
||||
return nil, noMatch
|
||||
}
|
||||
return &Lambda{args: args, body: body}, nil
|
||||
return &Lambda{params: args, body: body}, nil
|
||||
}
|
||||
|
||||
func parseConditional(in *Input) (Expression, error) {
|
||||
openingParens, ok := in.Pop()
|
||||
if !ok {
|
||||
return nil, noMatch
|
||||
}
|
||||
if !openingParens.Equals(Lparen) {
|
||||
return nil, noMatch
|
||||
}
|
||||
idx, ok := in.Find(Lparen, Rparen)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("unmatched parenthesis starting at %s", openingParens.Position())
|
||||
}
|
||||
decl := in.Take(idx)
|
||||
_, ok = in.Pop()
|
||||
tok, ok := decl.Pop()
|
||||
if !ok {
|
||||
return nil, noMatch
|
||||
}
|
||||
if !tok.Equals(If) {
|
||||
return nil, noMatch
|
||||
}
|
||||
predicate, err := consume(decl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ifTrue, err := consume(decl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
ifFalse, err := consume(decl)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &Conditional{predicate: predicate, ifTrue: ifTrue, ifFalse: ifFalse}, nil
|
||||
}
|
||||
|
||||
type ParserFunc func(*Input) (Expression, error)
|
||||
|
|
@ -263,6 +268,7 @@ func consume(in *Input) (n Expression, err error) {
|
|||
var parseFunctions = []ParserFunc{
|
||||
parseQuotedObject,
|
||||
parseLambda,
|
||||
parseConditional,
|
||||
parseLet,
|
||||
parseList,
|
||||
parseSymbol,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue