backup
This commit is contained in:
parent
0cd6040a1f
commit
c1f75bb980
6 changed files with 140 additions and 67 deletions
|
|
@ -235,6 +235,11 @@ type Symbol struct {
|
||||||
expr Expression
|
expr Expression
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type Param struct {
|
||||||
|
id *Identifier
|
||||||
|
t Type
|
||||||
|
}
|
||||||
|
|
||||||
func (v *Symbol) Step() (Expression, error) {
|
func (v *Symbol) Step() (Expression, error) {
|
||||||
if v.expr == nil {
|
if v.expr == nil {
|
||||||
return nil, fmt.Errorf("unbound symbol %s at %s", v.id, v.id.position)
|
return nil, fmt.Errorf("unbound symbol %s at %s", v.id, v.id.position)
|
||||||
|
|
|
||||||
30
input.go
30
input.go
|
|
@ -42,12 +42,12 @@ func (in *Input) Seek(i int) {
|
||||||
in.index = i
|
in.index = i
|
||||||
}
|
}
|
||||||
|
|
||||||
func (in *Input) Take(amount int) *Input {
|
func (in *Input) Take(offset int) *Input {
|
||||||
var out = &Input{
|
var out = &Input{
|
||||||
index: 0,
|
index: 0,
|
||||||
input: in.input[in.index : in.index+amount],
|
input: in.input[in.index : in.index+offset],
|
||||||
}
|
}
|
||||||
in.index += amount
|
in.index += offset
|
||||||
return out
|
return out
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -70,3 +70,27 @@ func (in *Input) Find(open, close *Token) (int, bool) {
|
||||||
return 0, false
|
return 0, false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (in *Input) TakeParens(open, close *Token) (*Input, error) {
|
||||||
|
if in.input[in.index].Equals(open) {
|
||||||
|
return nil, noMatch
|
||||||
|
}
|
||||||
|
start := in.index
|
||||||
|
level := 1
|
||||||
|
idx := slices.IndexFunc(in.input[start+1:], func(a Lexeme) bool {
|
||||||
|
switch {
|
||||||
|
case a.Equals(open):
|
||||||
|
level++
|
||||||
|
case a.Equals(close):
|
||||||
|
level--
|
||||||
|
return level == 0
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
})
|
||||||
|
if idx > -1 {
|
||||||
|
_ = in.Take(idx + 1)
|
||||||
|
return &Input{index: 0, input: in.input[start+1 : idx]}, nil
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("unmatched parenthesis starting at %s", in.Peek(start).Position())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
||||||
22
lex.go
22
lex.go
|
|
@ -22,31 +22,35 @@ func (p *position) Position() position {
|
||||||
return *p
|
return *p
|
||||||
}
|
}
|
||||||
|
|
||||||
type Range [2]position
|
type (
|
||||||
|
Range [2]position
|
||||||
|
|
||||||
type token[T comparable] struct {
|
token[T comparable] struct {
|
||||||
position
|
position
|
||||||
value T
|
value T
|
||||||
}
|
}
|
||||||
|
|
||||||
type Lexeme interface {
|
Lexeme interface {
|
||||||
Position() position
|
Position() position
|
||||||
Equals(Lexeme) bool
|
Equals(Lexeme) bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type Id string
|
Id string
|
||||||
|
|
||||||
type Token token[string]
|
Token token[string]
|
||||||
|
|
||||||
type IntToken token[int]
|
IntToken token[int]
|
||||||
|
|
||||||
type FloatToken token[float64]
|
FloatToken token[float64]
|
||||||
|
|
||||||
type Identifier token[Id]
|
Identifier token[Id]
|
||||||
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Lparen = &Token{value: "("}
|
Lparen = &Token{value: "("}
|
||||||
Rparen = &Token{value: ")"}
|
Rparen = &Token{value: ")"}
|
||||||
|
LsquareBracket = &Token{value: "["}
|
||||||
|
RsquareBracket = &Token{value: "]"}
|
||||||
Space = &Token{value: " "}
|
Space = &Token{value: " "}
|
||||||
Tab = &Token{value: "\t"}
|
Tab = &Token{value: "\t"}
|
||||||
Newline = &Token{value: "\n"}
|
Newline = &Token{value: "\n"}
|
||||||
|
|
@ -107,7 +111,7 @@ func (t *Identifier) Equals(a Lexeme) bool {
|
||||||
|
|
||||||
var matchInt = regexp.MustCompile(`-?\d+`)
|
var matchInt = regexp.MustCompile(`-?\d+`)
|
||||||
var matchFloat = regexp.MustCompile(`-?\d+\.\d*`)
|
var matchFloat = regexp.MustCompile(`-?\d+\.\d*`)
|
||||||
var matchIdentifier = regexp.MustCompile(`[^\'() ]+`)
|
var matchIdentifier = regexp.MustCompile(`[^\'() \[\]]+`)
|
||||||
|
|
||||||
func lex(source string) (*Input, error) {
|
func lex(source string) (*Input, error) {
|
||||||
var (
|
var (
|
||||||
|
|
|
||||||
75
main.go
75
main.go
|
|
@ -28,18 +28,27 @@ func fullStep(e Expression) (Expression, error) {
|
||||||
|
|
||||||
func builtinFunctions(expr Expression) {
|
func builtinFunctions(expr Expression) {
|
||||||
functions := map[Id]BuiltInFunction{
|
functions := map[Id]BuiltInFunction{
|
||||||
// "quote": {
|
"+.": {
|
||||||
// t: &FunctionType{
|
t: &FunctionType{
|
||||||
// ret: &PrimInteger,
|
ret: &PrimFloat,
|
||||||
// params: ,
|
params: []Type{&PrimFloat, &PrimFloat},
|
||||||
// },
|
},
|
||||||
// f: func(e []Expression) (Expression, error) {
|
f: func(args []Expression) (Expression, error) {
|
||||||
// if len(e) == 1 {
|
var sum FloatValue = 0
|
||||||
// return &Quoted{e[0]}, nil
|
for _, arg := range args {
|
||||||
// }
|
if !isValue(arg) {
|
||||||
// return &Quoted{&List{e}}, nil
|
panic("not a value")
|
||||||
// },
|
}
|
||||||
// },
|
switch x := arg.(type) {
|
||||||
|
case *FloatValue:
|
||||||
|
sum += *x
|
||||||
|
default:
|
||||||
|
panic("type error")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return &sum, nil
|
||||||
|
},
|
||||||
|
},
|
||||||
"+": {
|
"+": {
|
||||||
t: &FunctionType{
|
t: &FunctionType{
|
||||||
ret: &PrimInteger,
|
ret: &PrimInteger,
|
||||||
|
|
@ -61,27 +70,27 @@ func builtinFunctions(expr Expression) {
|
||||||
return &sum, nil
|
return &sum, nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// "-": func(args []Expression) (Expression, error) {
|
"-": {
|
||||||
// v0, ok := args[0].(*IntValue)
|
t: &FunctionType{
|
||||||
// if !ok {
|
ret: &PrimInteger,
|
||||||
// return nil, fmt.Errorf("integer value was expected")
|
params: []Type{&PrimInteger, &PrimInteger},
|
||||||
// }
|
},
|
||||||
// v1, ok := args[1].(*IntValue)
|
f: func(args []Expression) (Expression, error) {
|
||||||
// if !ok {
|
var sum IntValue = 0
|
||||||
// return nil, fmt.Errorf("integer value was expected")
|
for _, arg := range args {
|
||||||
// }
|
if !isValue(arg) {
|
||||||
// var result IntValue = (*v0 - *v1)
|
panic("not a value")
|
||||||
// return &result, nil
|
}
|
||||||
// },
|
switch x := arg.(type) {
|
||||||
// "=": func(args []Expression) (Expression, error) {
|
case *IntValue:
|
||||||
// if reflect.TypeOf(args[0]) != reflect.TypeOf(args[1]) {
|
sum += *x
|
||||||
// return nil, fmt.Errorf("unmatched types")
|
default:
|
||||||
// }
|
panic("type error")
|
||||||
// v0 := reflect.ValueOf(args[0])
|
}
|
||||||
// v1 := reflect.ValueOf(args[1])
|
}
|
||||||
// var result BoolValue = BoolValue(v0.Equal(v1))
|
return &sum, nil
|
||||||
// return &result, nil
|
},
|
||||||
// },
|
},
|
||||||
}
|
}
|
||||||
for id, f := range functions {
|
for id, f := range functions {
|
||||||
expr.Substitute(id, &f)
|
expr.Substitute(id, &f)
|
||||||
|
|
|
||||||
35
parse.go
35
parse.go
|
|
@ -96,6 +96,35 @@ func parseValue(in *Input) (Expression, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func parseParamList(in *Input) (Expression, error) {
|
||||||
|
list, err := in.TakeParens(Lparen, Rparen)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var params []*Symbol
|
||||||
|
for list.Len() > 0 {
|
||||||
|
p, err := list.TakeParens(LsquareBracket, RsquareBracket)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if p.Len() != 2 {
|
||||||
|
return nil, fmt.Errorf("expected parameter in the following form: [identifier type]")
|
||||||
|
}
|
||||||
|
id, ok := p.Peek(0).(*Identifier)
|
||||||
|
if !ok {
|
||||||
|
return nil, noMatch
|
||||||
|
}
|
||||||
|
typ, ok := p.Peek(1).(*Identifier)
|
||||||
|
if !ok {
|
||||||
|
return nil, noMatch
|
||||||
|
}
|
||||||
|
params = append(params, &Symbol{
|
||||||
|
id: ,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
return args, nil
|
||||||
|
}
|
||||||
|
|
||||||
func parseList(in *Input) (Expression, error) {
|
func parseList(in *Input) (Expression, error) {
|
||||||
openingParens, ok := in.Pop()
|
openingParens, ok := in.Pop()
|
||||||
if !ok {
|
if !ok {
|
||||||
|
|
@ -192,11 +221,7 @@ func parseLambda(in *Input) (Expression, error) {
|
||||||
return nil, fmt.Errorf("unmatched parenthesis starting at %s", openingParens.Position())
|
return nil, fmt.Errorf("unmatched parenthesis starting at %s", openingParens.Position())
|
||||||
}
|
}
|
||||||
decl := in.Take(idx)
|
decl := in.Take(idx)
|
||||||
tok, ok := decl.Pop()
|
if tok, ok := decl.Pop(); !ok || !tok.Equals(LambdaTok) {
|
||||||
if !ok {
|
|
||||||
return nil, noMatch
|
|
||||||
}
|
|
||||||
if !tok.Equals(LambdaTok) {
|
|
||||||
return nil, noMatch
|
return nil, noMatch
|
||||||
}
|
}
|
||||||
l, err := parseList(decl)
|
l, err := parseList(decl)
|
||||||
|
|
|
||||||
6
type.go
6
type.go
|
|
@ -84,6 +84,12 @@ func (fa *FunctionType) Equal(b Type) bool {
|
||||||
return fa.ret.Equal(fb.ret)
|
return fa.ret.Equal(fb.ret)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func FromId(id Id) (Type, error) {
|
||||||
|
// switch id {
|
||||||
|
// case "integer":
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
// func (fa *VariadicListType) Equal(b Type) bool {
|
// func (fa *VariadicListType) Equal(b Type) bool {
|
||||||
// return false
|
// return false
|
||||||
// }
|
// }
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue