diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/anglais.iml b/.idea/anglais.iml new file mode 100644 index 0000000..11646b4 --- /dev/null +++ b/.idea/anglais.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/inspectionProfiles/Project_Default.xml b/.idea/inspectionProfiles/Project_Default.xml new file mode 100644 index 0000000..6c7658f --- /dev/null +++ b/.idea/inspectionProfiles/Project_Default.xml @@ -0,0 +1,10 @@ + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..36d0426 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/core/compiler.go b/core/compiler.go index 83098d5..36f0f7a 100644 --- a/core/compiler.go +++ b/core/compiler.go @@ -977,41 +977,6 @@ func (c *Compiler) compileAssignFromStack(to Node, sig TypeSignature, declare bo } return sig, nil - case IndexNodeType: - if declare { - return nil, c.error(fmt.Sprintf("cannot declare an indexed item"), to) - } - - n := to.(*IndexNode) - - ssig, err := c.compile(n.source) - if err != nil { - return nil, err - } - - isig, err := c.compile(n.index) - if err != nil { - return nil, err - } - - if isig.Type() != TypeInteger { - return nil, c.error(fmt.Sprintf("cannot index into list with non-integer (%s)", isig), n.index) - } - - switch ssig.Type() { - case TypeList: - lsig := ssig.(*ListSignature) - if !c.typeMatches(sig, lsig.Contents) { - return nil, c.error(fmt.Sprintf("cannot assign value of type %s to list with items of type %s", sig, lsig.Contents), to) - } - - c.add(InstructionSetIndexList) - default: - return nil, c.error(fmt.Sprintf("cannot set index of %s", ssig.Type()), n.source) - } - - return sig, nil - default: return nil, c.error(fmt.Sprintf("cannot assign to %s", to.Type()), to) } diff --git a/core/types.go b/core/types.go index 81dafd8..6fe7c99 100644 --- a/core/types.go +++ b/core/types.go @@ -487,27 +487,6 @@ func quickComposite(a ...TypeSignature) TypeSignature { return s } -func simplifyComposite(a TypeSignature) TypeSignature { - var atoms []TypeSignature - - s := NewStack[TypeSignature](16) - s.Push(a) - - for s.Current > 0 { - i := s.Pop() - - c, ok := i.(*CompositeSignature) - if !ok { - - atoms = append(atoms, i) - } else { - s.Push(c.A, c.B) - } - } - - return quickComposite(atoms...) -} - type InnerSignature struct{} func (*InnerSignature) Type() Type { diff --git a/core/values.go b/core/values.go index efb5f41..8f95a1c 100644 --- a/core/values.go +++ b/core/values.go @@ -117,12 +117,8 @@ type Value interface { // Get a member from the value. An error is returned if the member does not exist Get(string) (Value, error) - // Copy create a copy of the value. A copy is a direct copy for small data (numbers) and a copy of pointer - // for bigger data (lists, tuples, dicts) - Copy() Value - - // Clone create a clone of the value. A clone is new data for all data. - //Clone() Value + // Clone create a clone of the value. The returned value is a pointer to a new value of the same type as the value. + Clone() Value } type NilValue struct{} @@ -147,7 +143,7 @@ func (v *NilValue) Get(_ string) (Value, error) { return nil, errors.New("nil has no properties") } -func (v *NilValue) Copy() Value { +func (v *NilValue) Clone() Value { return &NilValue{} } @@ -179,7 +175,7 @@ func (v *BoolValue) Get(_ string) (Value, error) { return nil, errors.New("booleans have no properties") } -func (v *BoolValue) Copy() Value { +func (v *BoolValue) Clone() Value { return &BoolValue{ v.Boolean, } @@ -262,11 +258,11 @@ func (v *ObjectValue) Get(key string) (Value, error) { } } -func (v *ObjectValue) Copy() Value { +func (v *ObjectValue) Clone() Value { m := make(map[string]Value, len(v.Members)) for name, mem := range v.Members { - m[name] = mem.Copy() + m[name] = mem.Clone() } return &ObjectValue{ @@ -307,7 +303,7 @@ func (v *FloatValue) Get(_ string) (Value, error) { return nil, errors.New("numbers have no properties") } -func (v *FloatValue) Copy() Value { +func (v *FloatValue) Clone() Value { return &FloatValue{ v.Number, } @@ -338,7 +334,7 @@ func (v *IntegerValue) Get(_ string) (Value, error) { return nil, errors.New("numbers have no properties") } -func (v *IntegerValue) Copy() Value { +func (v *IntegerValue) Clone() Value { return &IntegerValue{ new(big.Int).Set(v.Number), } @@ -431,7 +427,7 @@ func (v *StringValue) Get(key string) (Value, error) { return nil, errors.New(fmt.Sprintf("string has no property \"%s\"", key)) } -func (v *StringValue) Copy() Value { +func (v *StringValue) Clone() Value { return &StringValue{ v.Text, } @@ -598,9 +594,15 @@ func (v *ListValue) Get(key string) (Value, error) { return nil, errors.New(fmt.Sprintf("list has no property \"%s\"", key)) } -func (v *ListValue) Copy() Value { +func (v *ListValue) Clone() Value { + n := make([]Value, len(v.Items)) + + for i, item := range v.Items { + n[i] = item.Clone() + } + return &ListValue{ - v.Items, + n, } } @@ -633,9 +635,13 @@ func (v *TupleValue) DebugString() string { return v.String() } -func (v *TupleValue) Copy() Value { +func (v *TupleValue) Clone() Value { + n := make([]Value, len(v.Items)) + for i, item := range v.Items { + n[i] = item.Clone() + } return &TupleValue{ - v.Items, + n, } } @@ -712,7 +718,7 @@ func (v *FunctionValue) Get(_ string) (Value, error) { return nil, errors.New("functions have no properties") } -func (v *FunctionValue) Copy() Value { +func (v *FunctionValue) Clone() Value { return &FunctionValue{ v.Name, v.Params, @@ -752,7 +758,7 @@ func (v *BuiltinFunctionValue) Get(_ string) (Value, error) { return nil, errors.New("functions have no properties") } -func (v *BuiltinFunctionValue) Copy() Value { +func (v *BuiltinFunctionValue) Clone() Value { return &BuiltinFunctionValue{ v.Name, v.Signature, @@ -801,7 +807,7 @@ func (v *RecordValue) DebugString() string { return v.String() } -func (v *RecordValue) Copy() Value { +func (v *RecordValue) Clone() Value { return &RecordValue{ v.Entries, } diff --git a/core/vm.go b/core/vm.go index f07890f..22a568e 100644 --- a/core/vm.go +++ b/core/vm.go @@ -152,14 +152,10 @@ const ( // is the index. [..., container, index] -> [..., item] InstructionIndexTuple // InstructionIndexString index into a string. The lower item is the container, and the top item - // is the index. [..., container, index] -> [..., item]. Produces a new string with only the character - // at the indexed position + // is the index. [..., container, index] -> [..., item]. Produces a new string with the character + // at the position InstructionIndexString - // InstructionSetIndexList set the item at a given index in a list. - // [..., item, container, index] -> [..., item] - InstructionSetIndexList - // InstructionBreakpoint for debugging purposes InstructionBreakpoint ) @@ -642,7 +638,7 @@ var DefaultGlobals = map[string]Value{ n, _ := v.Number.Float64() return &FloatValue{n}, nil case *FloatValue: - return v.Copy(), nil + return v.Clone(), nil case *StringValue: num, err := strconv.ParseFloat(v.Text, FloatSize) if err != nil { @@ -982,7 +978,7 @@ func (vm *VM) Next() bool { vm.Stack.Push(v) case InstructionSetLocal: - value := vm.Stack.Peek().Copy() + value := vm.Stack.Peek().Clone() name := vm.GetConstant(vm.NextByte()).(*StringValue).Text vm.setVar(name, value) @@ -990,7 +986,7 @@ func (vm *VM) Next() bool { case InstructionDeclareLocal: vm.addVar( vm.GetConstant(vm.NextByte()).(*StringValue).Text, - vm.Stack.Peek().Copy(), + vm.Stack.Peek().Clone(), ) case InstructionGetGlobal: @@ -1074,7 +1070,7 @@ func (vm *VM) Next() bool { vm.Stack.Push(r, l) case InstructionDuplicate: - vm.Stack.Push(vm.Stack.Peek().Copy()) + vm.Stack.Push(vm.Stack.Peek().Clone()) case InstructionAccessProperty: source := vm.Stack.Pop() @@ -1116,7 +1112,7 @@ func (vm *VM) Next() bool { vm.error(fmt.Sprintf("index %d out of bounds", n)) } - vm.Stack.Push(l.Items[n].Copy()) + vm.Stack.Push(l.Items[n].Clone()) case InstructionIndexTuple: i := vm.Stack.Pop().(*IntegerValue) @@ -1128,7 +1124,7 @@ func (vm *VM) Next() bool { vm.error(fmt.Sprintf("index %d out of bounds", n)) } - vm.Stack.Push(t.Items[n].Copy()) + vm.Stack.Push(t.Items[n].Clone()) case InstructionIndexString: i := vm.Stack.Pop().(*IntegerValue) @@ -1142,18 +1138,6 @@ func (vm *VM) Next() bool { vm.Stack.Push(&StringValue{string(s.Text[n])}) - case InstructionSetIndexList: - n := vm.Stack.Pop().(*IntegerValue) - l := vm.Stack.Pop().(*ListValue) - - i := n.Number.Int64() - - if i < 0 || int64(len(l.Items)) <= i { - vm.error(fmt.Sprintf("index %d out of bounds", i)) - } - - l.Items[i] = vm.Stack.Peek().Copy() - case InstructionBreakpoint: /* // I'm keeping this @@ -1300,7 +1284,7 @@ func (vm *VM) HasNext() bool { } func (vm *VM) GetConstant(id Bytecode) Value { - return vm.chunk.Constants[id].Copy() + return vm.chunk.Constants[id].Clone() } func (vm *VM) ReadConstant() Value { diff --git a/examples/fib.ang b/examples/fib.ang index 4860a1e..63a432a 100644 --- a/examples/fib.ang +++ b/examples/fib.ang @@ -3,9 +3,14 @@ fn range(from: int, to: int) -> (fn() -> (int, bool)) { i := from - 1 + end := to - 1 fn() -> (int, bool) { - (i = i+1, i+1 < to) + if i < end { + (i = i+1, true) + } else { + (-1, false) + } } } diff --git a/examples/list.ang b/examples/list.ang index d34887e..9866d3e 100644 --- a/examples/list.ang +++ b/examples/list.ang @@ -1,6 +1,6 @@ # Empty list -println([]any) +println([]) # List with items println([3, 1, 4, 1, 5, 9, 2, 6, 5]) @@ -8,25 +8,25 @@ println([3, 1, 4, 1, 5, 9, 2, 6, 5]) # List with items of different types println(["", "私はかっこいいです。", true, nil, nil, 1, 2]) -a := []int +a := [] -a.push(1) -a.push(2) +a = a + [1] +a = a + [2] println(a) -list := []int +list := [] x := 0 for n in 0..100 { x = x + 2*n + 1 - list.push(x) + list = list + [x] } println(list) -println(list.map(fn(a: int) -> int { +println(list.map(func(a) { return a - 1 })) println(list.length()) diff --git a/examples/recursive.ang b/examples/recursive.ang index f30109f..caa0e37 100644 --- a/examples/recursive.ang +++ b/examples/recursive.ang @@ -1,15 +1,14 @@ # This program computes the fibonacci numbers using recursion (O(2^n)) # It is very slow -fn fib(x: number) number { +func fib(x: number) number { if x <= 1 { - x - } else { - fib(x - 1) + fib(x - 2) + return x } + return fib(x - 1) + fib(x - 2) } n := 0 while n < 100 { - println(fib(n)) + write(str(fib(n))) n = n + 1 } diff --git a/foo.ang b/foo.ang deleted file mode 100644 index e69de29..0000000 diff --git a/go.work.sum b/go.work.sum deleted file mode 100644 index 2d35219..0000000 --- a/go.work.sum +++ /dev/null @@ -1 +0,0 @@ -github.com/alecthomas/repr v0.5.2/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4= diff --git a/lib/list.ang b/lib/list.ang index 792751f..254912d 100644 --- a/lib/list.ang +++ b/lib/list.ang @@ -1,5 +1,5 @@ -fn map(list: [T], f: fn(T) -> R) -> [R] { +fn ([T]) map(f: fn(T) -> R) -> [R] { out := [] for v in list.iter() { diff --git a/lib/math.ang b/lib/math.ang index 9dac01a..120e60e 100644 --- a/lib/math.ang +++ b/lib/math.ang @@ -249,5 +249,3 @@ fn tan(x: float) -> float { # todo 0.0 } - -(E:, PI:, sqrt:, log:, ln:, exp:, pow:) diff --git a/lib/testing.ang b/lib/testing.ang index 82e7b77..59aed2c 100644 --- a/lib/testing.ang +++ b/lib/testing.ang @@ -1,25 +1,25 @@ NAMESPACE := "" -fn namespace(name: str, test: fn()) { +func namespace(name: string, test: func()) { NAMESPACE = name test() } -fn eq(a: T, b: T) { +func assertEqual(a: any, b: any) { if a != b { - println(format("assertion error: % should (but doesn't) equal %", [a, b])) + write(format("assertion error: % should (but doesn't) equal %", [a, b])) exit(1) } else if env("DEBUG") != "" { - println(format("assertion success: % equals %", [a, b])) + write(format("assertion success: % equals %", [a, b])) } } -fn neq(a: T, b: T) { +func assertNotEqual(a: any, b: any) { if a == b { - println(format("assertion error: % shouldn't (but does) equal %", [a, b])) + write(format("assertion error: % shouldn't (but does) equal %", [a, b])) exit(1) } else if env("DEBUG") != "" { - println(format("assertion success: % doesn't equal %", [a, b])) + write(format("assertion success: % doesn't equal %", [a, b])) } } diff --git a/tests/list.ang b/tests/list.ang index e98fcf8..8554f14 100644 --- a/tests/list.ang +++ b/tests/list.ang @@ -34,10 +34,3 @@ assertEq("the, first, time".split(", "), ["the", "first", "time"]) # list indexing assertEq([1, 2, 3].at(1), 2) assertEq(["a", "b", "c"].at(2), "c") - -# mutating list -a := [1, 2, 3] -assertEq(a, [1, 2, 3]) - -a[1] = 4 -assertEq(a, [1, 4, 3]) diff --git a/tests/tuple.ang b/tests/tuple.ang index 65e99e9..81aa508 100644 --- a/tests/tuple.ang +++ b/tests/tuple.ang @@ -9,10 +9,3 @@ fn neighbours(n: int) -> (int, int) { } assertEq(neighbours(2), (1, 3)) - -a := (1, 2) -assertEq(a, (1, 2)) - -(x, y) := a -assertEq(x, 1) -assertEq(y, 2)