This commit is contained in:
silva guimaraes 2025-05-25 21:56:22 -03:00
parent 7c40723537
commit 8f5b16878f
4 changed files with 316 additions and 144 deletions

189
parse.go
View file

@ -6,22 +6,25 @@ import (
"strings"
)
var noMatch = errors.New("no match")
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)
// Visit(func(Expression) error)
}
type List struct {
els []Expression
}
type Value[T interface{ *Int | int | Function }] struct {
type Value[T interface{ int | float64 | Function }] struct {
value T
// rng Range
}
type Quoted struct {
@ -29,14 +32,23 @@ type Quoted struct {
}
type Declaration struct {
variables []*Symbol
body []Expression
}
type Lambda struct {
args []*Symbol
body []Expression
}
type Symbol struct {
id *Identifier
expr Expression
}
type Lambda struct {
args []*Identifier
body []Expression
}
// type Progn struct {
// *List
// }
func (v Value[T]) String() string {
return fmt.Sprint(v.value)
@ -54,19 +66,31 @@ func (v List) String() string {
return fmt.Sprintf("(%s)", strings.Join(s, " "))
}
func (v *Lambda) String() string {
// var args = new(List)
// args.els = append(args.els, v.args...)
//
// var s []string
// for _, e := range v.args {
// s = append(s, fmt.Sprint(e))
// }
return "fuck you"
func (v Lambda) String() string {
var args List
for _, arg := range v.args {
args.els = append(args.els, arg)
}
var s []string
for _, e := range v.body {
s = append(s, fmt.Sprint(e))
}
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)
}
func parseQuotedObject(in *Input) (Expression, error) {
l := in.Pop()
l, ok := in.Pop()
if !ok {
return nil, noMatch
}
switch {
case l.Equals(SingleQuote):
n, err := consume(in)
@ -80,27 +104,38 @@ func parseQuotedObject(in *Input) (Expression, error) {
}
func parseSymbol(in *Input) (Expression, error) {
l := in.Pop()
l, ok := in.Pop()
if !ok {
return nil, noMatch
}
switch x := l.(type) {
case *Identifier:
return x, nil
return &Symbol{id: x}, nil
default:
return nil, noMatch
}
}
func parseValue(in *Input) (Expression, error) {
l := in.Pop()
l, ok := in.Pop()
if !ok {
return nil, noMatch
}
switch x := l.(type) {
case *Int:
return &Value[*Int]{x}, nil
return &Value[int]{x.value}, nil
case *Float:
return &Value[float64]{x.value}, nil
default:
return nil, noMatch
}
}
func parseList(in *Input) (Expression, error) {
openingParens := in.Pop()
openingParens, ok := in.Pop()
if !ok {
return nil, noMatch
}
if !openingParens.Equals(Lparen) {
return nil, noMatch
}
@ -117,28 +152,18 @@ func parseList(in *Input) (Expression, error) {
}
args.els = append(args.els, arg)
}
_ = in.Pop()
_, ok = in.Pop()
if !ok {
return nil, noMatch
}
return args, nil
}
func parseLet(in *Input) (Expression, error) {
token := in.Pop()
if !token.Equals(Let) {
return nil, noMatch
}
id, ok := in.Pop().(*Identifier)
openingParens, ok := in.Pop()
if !ok {
return nil, noMatch
}
expr, err := consume(in)
if err != nil {
return nil, noMatch
}
return &Declaration{id: id, expr: expr}, nil
}
func parseLambda(in *Input) (Expression, error) {
openingParens := in.Pop()
if !openingParens.Equals(Lparen) {
return nil, noMatch
}
@ -147,7 +172,61 @@ func parseLambda(in *Input) (Expression, error) {
return nil, fmt.Errorf("unmatched parenthesis starting at %s", openingParens.Position())
}
decl := in.Take(idx)
tok := decl.Pop()
tok, ok := decl.Pop()
if !ok {
return nil, noMatch
}
if !tok.Equals(Let) {
return nil, noMatch
}
l, err := parseList(decl)
if err != nil {
return nil, err
}
list, ok := l.(*List)
if !ok {
return nil, noMatch
}
var variables []*Symbol
for _, e := range list.els {
l, ok := e.(*List)
if !ok {
return nil, noMatch
}
if len(l.els) != 2 {
return nil, noMatch
}
d, ok := l.els[0].(*Symbol)
if !ok {
return nil, noMatch
}
d.expr = l.els[1]
variables = append(variables, d)
}
body, err := consumeAll(decl)
if err != nil {
return nil, err
}
return &Declaration{variables: variables, body: body}, nil
}
func parseLambda(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)
tok, ok := decl.Pop()
if !ok {
return nil, noMatch
}
if !tok.Equals(LambdaTok) {
return nil, noMatch
}
@ -159,23 +238,22 @@ func parseLambda(in *Input) (Expression, error) {
if !ok {
return nil, noMatch
}
var args []*Identifier
var args []*Symbol
for _, e := range list.els {
id, ok := e.(*Identifier)
id, ok := e.(*Symbol)
if !ok {
return nil, noMatch
}
args = append(args, id)
}
var body []Expression
for decl.Len() > 0 {
n, err := consume(decl)
if err != nil {
return nil, err
}
body = append(body, n)
body, err := consumeAll(decl)
if err != nil {
return nil, err
}
_, ok = in.Pop()
if !ok {
return nil, noMatch
}
_ = in.Pop()
return &Lambda{args: args, body: body}, nil
}
@ -185,10 +263,10 @@ func consume(in *Input) (n Expression, err error) {
var parseFunctions = []ParserFunc{
parseQuotedObject,
parseLambda,
parseLet,
parseList,
parseSymbol,
parseValue,
parseLet,
}
for _, f := range parseFunctions {
start := in.Index()
@ -205,3 +283,16 @@ func consume(in *Input) (n Expression, err error) {
}
return nil, fmt.Errorf("unrecognized construction: %s", in)
}
func consumeAll(in *Input) (e []Expression, err error) {
for in.Len() > 0 {
start := in.Index()
n, err := consume(in)
if err != nil {
in.Seek(start)
return nil, err
}
e = append(e, n)
}
return e, err
}