style: moved functions around
This commit is contained in:
@@ -4,14 +4,14 @@ import (
|
||||
"fmt"
|
||||
|
||||
"git.maximhutz.com/max/lambda/pkg/lambda"
|
||||
"git.maximhutz.com/max/lambda/pkg/saccharine/ast"
|
||||
"git.maximhutz.com/max/lambda/pkg/saccharine"
|
||||
)
|
||||
|
||||
func convertAtom(n *ast.Atom) lambda.Expression {
|
||||
func convertAtom(n *saccharine.Atom) lambda.Expression {
|
||||
return lambda.NewVariable(n.Name)
|
||||
}
|
||||
|
||||
func convertAbstraction(n *ast.Abstraction) lambda.Expression {
|
||||
func convertAbstraction(n *saccharine.Abstraction) lambda.Expression {
|
||||
result := SaccharineToLambda(n.Body)
|
||||
|
||||
parameters := n.Parameters
|
||||
@@ -31,7 +31,7 @@ func convertAbstraction(n *ast.Abstraction) lambda.Expression {
|
||||
return result
|
||||
}
|
||||
|
||||
func convertApplication(n *ast.Application) lambda.Expression {
|
||||
func convertApplication(n *saccharine.Application) lambda.Expression {
|
||||
result := SaccharineToLambda(n.Abstraction)
|
||||
|
||||
arguments := []lambda.Expression{}
|
||||
@@ -47,13 +47,13 @@ func convertApplication(n *ast.Application) lambda.Expression {
|
||||
return result
|
||||
}
|
||||
|
||||
func reduceLet(s *ast.LetStatement, e lambda.Expression) lambda.Expression {
|
||||
func reduceLet(s *saccharine.LetStatement, e lambda.Expression) lambda.Expression {
|
||||
var value lambda.Expression
|
||||
|
||||
if len(s.Parameters) == 0 {
|
||||
value = SaccharineToLambda(s.Body)
|
||||
} else {
|
||||
value = convertAbstraction(ast.NewAbstraction(s.Parameters, s.Body))
|
||||
value = convertAbstraction(saccharine.NewAbstraction(s.Parameters, s.Body))
|
||||
}
|
||||
|
||||
return lambda.NewApplication(
|
||||
@@ -62,7 +62,7 @@ func reduceLet(s *ast.LetStatement, e lambda.Expression) lambda.Expression {
|
||||
)
|
||||
}
|
||||
|
||||
func reduceDeclare(s *ast.DeclareStatement, e lambda.Expression) lambda.Expression {
|
||||
func reduceDeclare(s *saccharine.DeclareStatement, e lambda.Expression) lambda.Expression {
|
||||
freshVar := lambda.GenerateFreshName(lambda.GetFreeVariables(e))
|
||||
|
||||
return lambda.NewApplication(
|
||||
@@ -71,18 +71,18 @@ func reduceDeclare(s *ast.DeclareStatement, e lambda.Expression) lambda.Expressi
|
||||
)
|
||||
}
|
||||
|
||||
func reduceStatement(s ast.Statement, e lambda.Expression) lambda.Expression {
|
||||
func reduceStatement(s saccharine.Statement, e lambda.Expression) lambda.Expression {
|
||||
switch s := s.(type) {
|
||||
case *ast.DeclareStatement:
|
||||
case *saccharine.DeclareStatement:
|
||||
return reduceDeclare(s, e)
|
||||
case *ast.LetStatement:
|
||||
case *saccharine.LetStatement:
|
||||
return reduceLet(s, e)
|
||||
default:
|
||||
panic(fmt.Errorf("unknown statement type: %v", s))
|
||||
}
|
||||
}
|
||||
|
||||
func convertClause(n *ast.Clause) lambda.Expression {
|
||||
func convertClause(n *saccharine.Clause) lambda.Expression {
|
||||
result := SaccharineToLambda(n.Returns)
|
||||
|
||||
for i := len(n.Statements) - 1; i >= 0; i-- {
|
||||
@@ -92,15 +92,15 @@ func convertClause(n *ast.Clause) lambda.Expression {
|
||||
return result
|
||||
}
|
||||
|
||||
func SaccharineToLambda(n ast.Expression) lambda.Expression {
|
||||
func SaccharineToLambda(n saccharine.Expression) lambda.Expression {
|
||||
switch n := n.(type) {
|
||||
case *ast.Atom:
|
||||
case *saccharine.Atom:
|
||||
return convertAtom(n)
|
||||
case *ast.Abstraction:
|
||||
case *saccharine.Abstraction:
|
||||
return convertAbstraction(n)
|
||||
case *ast.Application:
|
||||
case *saccharine.Application:
|
||||
return convertApplication(n)
|
||||
case *ast.Clause:
|
||||
case *saccharine.Clause:
|
||||
return convertClause(n)
|
||||
default:
|
||||
panic(fmt.Errorf("unknown expression type: %T", n))
|
||||
|
||||
9
pkg/deltanet/deltanet.go
Normal file
9
pkg/deltanet/deltanet.go
Normal file
@@ -0,0 +1,9 @@
|
||||
// Package "deltanet" is a reduction strategy using ∆-nets.
|
||||
package deltanet
|
||||
|
||||
type Graph struct {
|
||||
nodes []Node
|
||||
}
|
||||
|
||||
type Node interface {
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package ast
|
||||
package saccharine
|
||||
|
||||
type Expression interface {
|
||||
IsExpression()
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
"fmt"
|
||||
|
||||
"git.maximhutz.com/max/lambda/pkg/iterator"
|
||||
"git.maximhutz.com/max/lambda/pkg/saccharine/ast"
|
||||
"git.maximhutz.com/max/lambda/pkg/saccharine/token"
|
||||
"git.maximhutz.com/max/lambda/pkg/trace"
|
||||
)
|
||||
@@ -75,8 +74,8 @@ func parseList[U any](i *TokenIterator, fn func(*TokenIterator) (U, error), mini
|
||||
}
|
||||
}
|
||||
|
||||
func parseAbstraction(i *TokenIterator) (*ast.Abstraction, error) {
|
||||
return iterator.Do(i, func(i *TokenIterator) (*ast.Abstraction, error) {
|
||||
func parseAbstraction(i *TokenIterator) (*Abstraction, error) {
|
||||
return iterator.Do(i, func(i *TokenIterator) (*Abstraction, error) {
|
||||
if _, err := parseToken(i, token.Slash, true); err != nil {
|
||||
return nil, trace.Wrap(err, "no function slash (col %d)", i.MustGet().Column)
|
||||
} else if parameters, err := parseList(i, parseString, 0); err != nil {
|
||||
@@ -86,13 +85,13 @@ func parseAbstraction(i *TokenIterator) (*ast.Abstraction, error) {
|
||||
} else if body, err := parseExpression(i); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return ast.NewAbstraction(parameters, body), nil
|
||||
return NewAbstraction(parameters, body), nil
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func parseApplication(i *TokenIterator) (*ast.Application, error) {
|
||||
return iterator.Do(i, func(i *TokenIterator) (*ast.Application, error) {
|
||||
func parseApplication(i *TokenIterator) (*Application, error) {
|
||||
return iterator.Do(i, func(i *TokenIterator) (*Application, error) {
|
||||
if _, err := parseToken(i, token.OpenParen, true); err != nil {
|
||||
return nil, trace.Wrap(err, "no openning brackets (col %d)", i.MustGet().Column)
|
||||
} else if expressions, err := parseList(i, parseExpression, 1); err != nil {
|
||||
@@ -100,21 +99,21 @@ func parseApplication(i *TokenIterator) (*ast.Application, error) {
|
||||
} else if _, err := parseToken(i, token.CloseParen, true); err != nil {
|
||||
return nil, trace.Wrap(err, "no closing brackets (col %d)", i.MustGet().Column)
|
||||
} else {
|
||||
return ast.NewApplication(expressions[0], expressions[1:]), nil
|
||||
return NewApplication(expressions[0], expressions[1:]), nil
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func parseAtom(i *TokenIterator) (*ast.Atom, error) {
|
||||
func parseAtom(i *TokenIterator) (*Atom, error) {
|
||||
if tok, err := parseToken(i, token.Atom, true); err != nil {
|
||||
return nil, trace.Wrap(err, "no variable (col %d)", i.Index())
|
||||
} else {
|
||||
return ast.NewAtom(tok.Value), nil
|
||||
return NewAtom(tok.Value), nil
|
||||
}
|
||||
}
|
||||
|
||||
func parseStatements(i *TokenIterator) ([]ast.Statement, error) {
|
||||
statements := []ast.Statement{}
|
||||
func parseStatements(i *TokenIterator) ([]Statement, error) {
|
||||
statements := []Statement{}
|
||||
|
||||
//nolint:errcheck
|
||||
parseList(i, parseBreak, 0)
|
||||
@@ -132,15 +131,15 @@ func parseStatements(i *TokenIterator) ([]ast.Statement, error) {
|
||||
return statements, nil
|
||||
}
|
||||
|
||||
func parseClause(i *TokenIterator, braces bool) (*ast.Clause, error) {
|
||||
func parseClause(i *TokenIterator, braces bool) (*Clause, error) {
|
||||
if braces {
|
||||
if _, err := parseToken(i, token.OpenBrace, true); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
var stmts []ast.Statement
|
||||
var last *ast.DeclareStatement
|
||||
var stmts []Statement
|
||||
var last *DeclareStatement
|
||||
var err error
|
||||
var ok bool
|
||||
|
||||
@@ -148,7 +147,7 @@ func parseClause(i *TokenIterator, braces bool) (*ast.Clause, error) {
|
||||
return nil, err
|
||||
} else if len(stmts) == 0 {
|
||||
return nil, fmt.Errorf("no statements in clause")
|
||||
} else if last, ok = stmts[len(stmts)-1].(*ast.DeclareStatement); !ok {
|
||||
} else if last, ok = stmts[len(stmts)-1].(*DeclareStatement); !ok {
|
||||
return nil, fmt.Errorf("this clause contains no final return value (col %d)", i.MustGet().Column)
|
||||
}
|
||||
|
||||
@@ -158,11 +157,11 @@ func parseClause(i *TokenIterator, braces bool) (*ast.Clause, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return ast.NewClause(stmts[:len(stmts)-1], last.Value), nil
|
||||
return NewClause(stmts[:len(stmts)-1], last.Value), nil
|
||||
}
|
||||
|
||||
func parseExpression(i *TokenIterator) (ast.Expression, error) {
|
||||
return iterator.Do(i, func(i *TokenIterator) (ast.Expression, error) {
|
||||
func parseExpression(i *TokenIterator) (Expression, error) {
|
||||
return iterator.Do(i, func(i *TokenIterator) (Expression, error) {
|
||||
passSoftBreaks(i)
|
||||
|
||||
switch peek := i.MustGet(); peek.Type {
|
||||
@@ -180,8 +179,8 @@ func parseExpression(i *TokenIterator) (ast.Expression, error) {
|
||||
})
|
||||
}
|
||||
|
||||
func parseLet(i *TokenIterator) (*ast.LetStatement, error) {
|
||||
return iterator.Do(i, func(i *TokenIterator) (*ast.LetStatement, error) {
|
||||
func parseLet(i *TokenIterator) (*LetStatement, error) {
|
||||
return iterator.Do(i, func(i *TokenIterator) (*LetStatement, error) {
|
||||
if parameters, err := parseList(i, parseString, 1); err != nil {
|
||||
return nil, err
|
||||
} else if _, err := parseToken(i, token.Assign, true); err != nil {
|
||||
@@ -189,20 +188,20 @@ func parseLet(i *TokenIterator) (*ast.LetStatement, error) {
|
||||
} else if body, err := parseExpression(i); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return ast.NewLet(parameters[0], parameters[1:], body), nil
|
||||
return NewLet(parameters[0], parameters[1:], body), nil
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
func parseDeclare(i *TokenIterator) (*ast.DeclareStatement, error) {
|
||||
func parseDeclare(i *TokenIterator) (*DeclareStatement, error) {
|
||||
if value, err := parseExpression(i); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return ast.NewDeclare(value), nil
|
||||
return NewDeclare(value), nil
|
||||
}
|
||||
}
|
||||
|
||||
func parseStatement(i *TokenIterator) (ast.Statement, error) {
|
||||
func parseStatement(i *TokenIterator) (Statement, error) {
|
||||
if let, letErr := parseLet(i); letErr == nil {
|
||||
return let, nil
|
||||
} else if declare, declErr := parseDeclare(i); declErr == nil {
|
||||
@@ -213,7 +212,7 @@ func parseStatement(i *TokenIterator) (ast.Statement, error) {
|
||||
}
|
||||
|
||||
// Given a list of tokens, attempt to parse it into an syntax tree.
|
||||
func Parse(tokens []token.Token) (ast.Expression, error) {
|
||||
func parse(tokens []token.Token) (Expression, error) {
|
||||
i := iterator.Of(tokens)
|
||||
|
||||
exp, err := parseClause(i, false)
|
||||
22
pkg/saccharine/saccharine.go
Normal file
22
pkg/saccharine/saccharine.go
Normal file
@@ -0,0 +1,22 @@
|
||||
// Package "saccharine" provides a simple language built on top of λ-calculus,
|
||||
// to facilitate productive coding using it.
|
||||
package saccharine
|
||||
|
||||
import (
|
||||
"git.maximhutz.com/max/lambda/pkg/saccharine/token"
|
||||
)
|
||||
|
||||
// Convert a piece of valid saccharine code into an expression.
|
||||
func Parse(code string) (Expression, error) {
|
||||
tokens, err := token.Parse(code)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return parse(tokens)
|
||||
}
|
||||
|
||||
// Convert a parsed saccharine expression back into source code.
|
||||
func Stringify(expression Expression) string {
|
||||
return stringifyExpression(expression)
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package ast
|
||||
package saccharine
|
||||
|
||||
type Statement interface {
|
||||
IsStatement()
|
||||
@@ -3,67 +3,65 @@ package saccharine
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"git.maximhutz.com/max/lambda/pkg/saccharine/ast"
|
||||
)
|
||||
|
||||
func stringifyAtom(n *ast.Atom) string {
|
||||
func stringifyAtom(n *Atom) string {
|
||||
return n.Name
|
||||
}
|
||||
|
||||
func stringifyAbstraction(n *ast.Abstraction) string {
|
||||
return "\\" + strings.Join(n.Parameters, " ") + "." + Stringify(n.Body)
|
||||
func stringifyAbstraction(n *Abstraction) string {
|
||||
return "\\" + strings.Join(n.Parameters, " ") + "." + stringifyExpression(n.Body)
|
||||
}
|
||||
|
||||
func stringifyApplication(n *ast.Application) string {
|
||||
arguments := []string{Stringify(n.Abstraction)}
|
||||
func stringifyApplication(n *Application) string {
|
||||
arguments := []string{stringifyExpression(n.Abstraction)}
|
||||
|
||||
for _, argument := range n.Arguments {
|
||||
arguments = append(arguments, Stringify(argument))
|
||||
arguments = append(arguments, stringifyExpression(argument))
|
||||
}
|
||||
|
||||
return "(" + strings.Join(arguments, " ") + ")"
|
||||
}
|
||||
|
||||
func stringifyLet(s *ast.LetStatement) string {
|
||||
return s.Name + " " + strings.Join(s.Parameters, " ") + " := " + Stringify(s.Body)
|
||||
func stringifyLet(s *LetStatement) string {
|
||||
return s.Name + " " + strings.Join(s.Parameters, " ") + " := " + stringifyExpression(s.Body)
|
||||
}
|
||||
|
||||
func stringifyDeclare(s *ast.DeclareStatement) string {
|
||||
return Stringify(s.Value)
|
||||
func stringifyDeclare(s *DeclareStatement) string {
|
||||
return stringifyExpression(s.Value)
|
||||
}
|
||||
|
||||
func stringifyStatement(s ast.Statement) string {
|
||||
func stringifyStatement(s Statement) string {
|
||||
switch s := s.(type) {
|
||||
case *ast.DeclareStatement:
|
||||
case *DeclareStatement:
|
||||
return stringifyDeclare(s)
|
||||
case *ast.LetStatement:
|
||||
case *LetStatement:
|
||||
return stringifyLet(s)
|
||||
default:
|
||||
panic(fmt.Errorf("unknown statement type: %v", s))
|
||||
}
|
||||
}
|
||||
|
||||
func stringifyClause(n *ast.Clause) string {
|
||||
func stringifyClause(n *Clause) string {
|
||||
stmts := ""
|
||||
|
||||
for _, statement := range n.Statements {
|
||||
stmts += stringifyStatement(statement) + "; "
|
||||
}
|
||||
|
||||
return "{ " + stmts + Stringify(n.Returns) + " }"
|
||||
return "{ " + stmts + stringifyExpression(n.Returns) + " }"
|
||||
}
|
||||
|
||||
// Convert an expression back into valid source code.
|
||||
func Stringify(n ast.Expression) string {
|
||||
func stringifyExpression(n Expression) string {
|
||||
switch n := n.(type) {
|
||||
case *ast.Atom:
|
||||
case *Atom:
|
||||
return stringifyAtom(n)
|
||||
case *ast.Abstraction:
|
||||
case *Abstraction:
|
||||
return stringifyAbstraction(n)
|
||||
case *ast.Application:
|
||||
case *Application:
|
||||
return stringifyApplication(n)
|
||||
case *ast.Clause:
|
||||
case *Clause:
|
||||
return stringifyClause(n)
|
||||
default:
|
||||
panic(fmt.Errorf("unknown expression type: %T", n))
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
package saccharine
|
||||
package token
|
||||
|
||||
import (
|
||||
"errors"
|
||||
@@ -6,7 +6,6 @@ import (
|
||||
"unicode"
|
||||
|
||||
"git.maximhutz.com/max/lambda/pkg/iterator"
|
||||
"git.maximhutz.com/max/lambda/pkg/saccharine/token"
|
||||
"git.maximhutz.com/max/lambda/pkg/trace"
|
||||
)
|
||||
|
||||
@@ -43,7 +42,7 @@ func parseCharacter(i *iterator.Iterator[rune], expected rune) (rune, error) {
|
||||
|
||||
// Pulls the next token from an iterator over runes. If it cannot, it will
|
||||
// return nil. If an error occurs, it will return that.
|
||||
func getToken(i *iterator.Iterator[rune]) (*token.Token, error) {
|
||||
func getToken(i *iterator.Iterator[rune]) (*Token, error) {
|
||||
index := i.Index()
|
||||
|
||||
if i.Done() {
|
||||
@@ -57,27 +56,27 @@ func getToken(i *iterator.Iterator[rune]) (*token.Token, error) {
|
||||
|
||||
switch {
|
||||
case letter == '(':
|
||||
return token.NewOpenParen(index), nil
|
||||
return NewOpenParen(index), nil
|
||||
case letter == ')':
|
||||
return token.NewCloseParen(index), nil
|
||||
return NewCloseParen(index), nil
|
||||
case letter == '.':
|
||||
return token.NewDot(index), nil
|
||||
return NewDot(index), nil
|
||||
case letter == '\\':
|
||||
return token.NewSlash(index), nil
|
||||
return NewSlash(index), nil
|
||||
case letter == '\n':
|
||||
return token.NewSoftBreak(index), nil
|
||||
return NewSoftBreak(index), nil
|
||||
case letter == '{':
|
||||
return token.NewOpenBrace(index), nil
|
||||
return NewOpenBrace(index), nil
|
||||
case letter == '}':
|
||||
return token.NewCloseBrace(index), nil
|
||||
return NewCloseBrace(index), nil
|
||||
case letter == ':':
|
||||
if _, err := parseCharacter(i, '='); err != nil {
|
||||
return nil, err
|
||||
} else {
|
||||
return token.NewAssign(index), nil
|
||||
return NewAssign(index), nil
|
||||
}
|
||||
case letter == ';':
|
||||
return token.NewHardBreak(index), nil
|
||||
return NewHardBreak(index), nil
|
||||
case unicode.IsSpace(letter):
|
||||
return nil, nil
|
||||
case isVariable(letter):
|
||||
@@ -91,16 +90,16 @@ func getToken(i *iterator.Iterator[rune]) (*token.Token, error) {
|
||||
}
|
||||
}
|
||||
|
||||
return token.NewAtom(string(atom), index), nil
|
||||
return NewAtom(string(atom), index), nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("unknown character '%v'", string(letter))
|
||||
}
|
||||
|
||||
// Parse a string into tokens.
|
||||
func GetTokens(input string) ([]token.Token, error) {
|
||||
func Parse(input string) ([]Token, error) {
|
||||
i := iterator.Of([]rune(input))
|
||||
tokens := []token.Token{}
|
||||
tokens := []Token{}
|
||||
errorList := []error{}
|
||||
|
||||
for !i.Done() {
|
||||
Reference in New Issue
Block a user