Skip to content

Commit

Permalink
Use ints in std. ARC error recovery. Functions borrow params by defau…
Browse files Browse the repository at this point in the history
…lt. Moving more opcodes to methods and inlines.
  • Loading branch information
fubark committed Sep 14, 2023
1 parent c500c18 commit b2b8d03
Show file tree
Hide file tree
Showing 59 changed files with 2,541 additions and 2,637 deletions.
2 changes: 1 addition & 1 deletion docs/hugo/content/docs/toc/control-flow.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ while iter.next() some entry:
print entry.name
```

`for` loops can iterate over a range that starts at a `float` (inclusive) to a target `float` (exclusive). When the range operator `..` is replaced with `..=`, the target number is inclusive. The range can be given a custom step.
`for` loops can iterate over a range that starts at a `int` (inclusive) to a target `int` (exclusive). When the range operator `..` is replaced with `..=`, the target `int` is inclusive. The range can be given a custom step.
```cy
for 0..100 each i:
print i -- 0, 1, 2, ... , 99
Expand Down
105 changes: 56 additions & 49 deletions docs/hugo/content/docs/toc/data-types.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,45 +20,52 @@ When other value types are coerced to the boolean type, the truthy value is dete
- Other objects and values are always `true`.

## Numbers.
### Floats.
`float` is the default number type and has an (IEEE 754) 64-bit floating point format.

Although a `float` represents a decimal number, it can also represent integers between -(2{{<sup "53">}}-1) and (2{{<sup "53">}}-1). Any integers beyond the safe integer range is not guaranteed to have a unique representation.
### Integers.
`int` is the default integer type. It has 48-bits and can represent integers in the range -(2{{<sup "47">}}) to 2{{<sup "47">}}-1.

When a numeric literal is used and the type can not be inferred, it will default to the `float` type:
When a numeric literal is used and the type can not be inferred, it will default to the `int` type:
```cy
var a = 123
```

Decimal and scientific notations always produce a `float` value:
Integer notations always produce a `int` value:
```cy
var a = 2.34567
var b = 123.0e4
var a = 0xFF -- hex.
a = 0o17 -- octal.
a = 0b1010 -- binary.
a = 0u'🐶' -- UTF-8 rune.
```

Arbitrary values can be converted to a `float` using the type as a function.
Arbitrary values can be converted to a `int` using the type as a function.
```cy
var a = '12.3'
var b = float(a)
var a = '123'
var b = int(a)
```

### Integers.
`int` is a number type that represents a 32-bit integer.
In addition to arithmetic operations, integers can also perform [bitwise operations]({{<relref "/docs/toc/syntax#bitwise-operators">}}).

### Floats.
`float` is the default floating point type. It has a (IEEE 754) 64-bit floating point format.

Although a `float` represents a decimal number, it can also represent integers between -(2{{<sup "53">}}-1) and (2{{<sup "53">}}-1). Any integers beyond the safe integer range is not guaranteed to have a unique representation.

A numeric literal can be used to create an `int` if the inferred type is an `int`:
A numeric literal can be used to create a `float` if the inferred type is a `float`:
```cy
a int = 123
a float = 123
```

Integer notations always produce a `int` value:
Decimal and scientific notations always produce a `float` value:
```cy
var a = 0xFF -- hex.
a = 0o17 -- octal.
a = 0b1010 -- binary.
a = 0u'🐶' -- UTF-8 rune.
var a = 2.34567
var b = 123.0e4
```

In addition to arithmetic operations, integers can also perform [bitwise operations]({{<relref "/docs/toc/syntax#bitwise-operators">}}).
Arbitrary values can be converted to a `float` using the type as a function.
```cy
var a = '12.3'
var b = float(a)
```

### Big Numbers.
Big numbers will be supported in a future version of Cyber.
Expand Down Expand Up @@ -154,22 +161,22 @@ func concat(self, str string) string
func endsWith(self, suffix string) bool
-- Returns whether the string ends with `suffix`.

func find(self, needle string) float?
func find(self, needle string) int?
-- Returns the first index of substring `needle` in the string or `none` if not found.

func findAnyRune(self, set string) float?
func findAnyRune(self, set string) int?
-- Returns the first index of any UTF-8 rune in `set` or `none` if not found.

func findRune(self, needle float) float?
func findRune(self, needle int) int?
-- Returns the first index of UTF-8 rune `needle` in the string or `none` if not found.

func insert(self, idx float, str string) string
func insert(self, idx int, str string) string
-- Returns a new string with `str` inserted at index `idx`.

func isAscii(self) bool
-- Returns whether the string contains all ASCII runes.

func len(self) float
func len(self) int
-- Returns the number of UTF-8 runes in the string.

func less(self, str string) bool
Expand All @@ -181,16 +188,16 @@ func lower(self) string
func replace(self, needle string, replacement string) string
-- Returns a new string with all occurrences of `needle` replaced with `replacement`. |

func repeat(self, n float) string
func repeat(self, n int) string
-- Returns a new string with this string repeated `n` times.

func runeAt(self, idx float) float
func runeAt(self, idx int) int
-- Returns the UTF-8 rune at index `idx`.

func slice(self, start float, end float) string
func slice(self, start int, end int) string
-- Returns a slice into this string from `start` to `end` (exclusive) indexes. This is equivalent to using the slice index operator `[start..end]`.

func sliceAt(self, idx float) string
func sliceAt(self, idx int) string
-- Returns the UTF-8 rune at index `idx` as a single rune string.

func split(self, delim string) List
Expand Down Expand Up @@ -235,7 +242,7 @@ print str[-1] -- "d"
### `type rawstring`
```cy
func byteAt(self, idx float) float
func byteAt(self, idx int) int
-- Returns the byte value (0-255) at the given index `idx`.

func concat(self, str string) string
Expand All @@ -244,25 +251,25 @@ func concat(self, str string) string
func endsWith(self, suffix string) bool
-- Returns whether the string ends with `suffix`.

func find(self, needle string) float?
func find(self, needle string) int?
-- Returns the first index of substring `needle` in the string or `none` if not found.

func findAnyRune(self, set string) float?
func findAnyRune(self, set string) int?
-- Returns the first index of any UTF-8 rune in `set` or `none` if not found.

func findRune(self, needle float) float?
func findRune(self, needle int) int?
-- Returns the first index of UTF-8 rune `needle` in the string or `none` if not found.

func insert(self, idx float, str string) string
func insert(self, idx int, str string) string
-- Returns a new string with `str` inserted at index `idx`.

func insertByte(self, idx float, byte float) string
func insertByte(self, idx int, byte int) string
-- Returns a new string with `byte` inserted at index `idx`.

func isAscii(self) bool
-- Returns whether the string contains all ASCII runes.

func len(self) float
func len(self) int
-- Returns the number of bytes in the string.

func less(self, str rawstring) bool
Expand All @@ -271,19 +278,19 @@ func less(self, str rawstring) bool
func lower(self) string
-- Returns this string in lowercase.

func repeat(self, n float) rawstring
func repeat(self, n int) rawstring
-- Returns a new rawstring with this rawstring repeated `n` times.

func replace(self, needle string, replacement string) string
-- Returns a new string with all occurrences of `needle` replaced with `replacement`.

func runeAt(self, idx float) float
func runeAt(self, idx int) int
-- Returns the UTF-8 rune at index `idx`. If the index does not begin a UTF-8 rune, `error.InvalidRune` is returned.

func slice(self, start float, end float) rawstring
func slice(self, start int, end int) rawstring
-- Returns a slice into this string from `start` to `end` (exclusive) indexes. This is equivalent to using the slice index operator `[start..end]`.

func sliceAt(self, idx float) string
func sliceAt(self, idx int) string
-- Returns the UTF-8 rune at index `idx` as a single rune string. If the index does not begin a UTF-8 rune, `error.InvalidRune` is returned.

func split(self, delim string) List
Expand Down Expand Up @@ -354,13 +361,13 @@ list.remove(1)
| ------------- | ----- |
| `append(val any) none` | Appends a value to the end of the list. |
| `concat(val any) none` | Concats the elements of another list to the end of this list. |
| `insert(idx float, val any) none` | Inserts a value at index `idx`. |
| `insert(idx int, val any) none` | Inserts a value at index `idx`. |
| `iterator() Iterator<any>` | Returns a new iterator over the list elements. |
| `joinString(separator any) string` | Returns a new string that joins the elements with `separator`. |
| `len() float` | Returns the number of elements in the list. |
| `pairIterator() PairIterator<float, any>` | Returns a new pair iterator over the list elements. |
| `remove(idx float) none` | Removes an element at index `idx`. |
| `resize(len float) none` | Resizes the list to `len` elements. If the new size is bigger, `none` values are appended to the list. If the new size is smaller, elements at the end of the list are removed. |
| `len() int` | Returns the number of elements in the list. |
| `pairIterator() PairIterator<int, any>` | Returns a new pair iterator over the list elements. |
| `remove(idx int) none` | Removes an element at index `idx`. |
| `resize(len int) none` | Resizes the list to `len` elements. If the new size is bigger, `none` values are appended to the list. If the new size is smaller, elements at the end of the list are removed. |
| `sort(less func (a, b) bool) none` | Sorts the list with the given `less` function. If element `a` should be ordered before `b`, the function should return `true` otherwise `false`. |
## Maps.
Expand Down Expand Up @@ -418,9 +425,9 @@ for map each val, key:
| Method | Summary |
| ------------- | ----- |
| `iterator() Iterator<any>` | Returns a new iterator over the map elements. |
| `pairIterator() PairIterator<float, any>` | Returns a new pair iterator over the map elements. |
| `pairIterator() PairIterator<any, any>` | Returns a new pair iterator over the map elements. |
| `remove(key any) none` | Removes the element with the given key `key`. |
| `size() float` | Returns the number of key-value pairs in the map. |
| `size() int` | Returns the number of key-value pairs in the map. |

## Objects.
Any value that isn't a primitive is an object. You can declare your own object types using the `type object` declaration. Object types are similar to structs and classes in other languages. You can declare members and methods. Unlike classes, there is no concept of inheritance at the language level.
Expand Down Expand Up @@ -475,7 +482,7 @@ type Fruit enum:

var fruit = Fruit.kiwi
print fruit -- 'Fruit.kiwi'
print float(fruit) -- '3'
print int(fruit) -- '3'
```
When the type of the value is known to be an enum, it can be assigned using a symbol literal.
```cy
Expand All @@ -489,5 +496,5 @@ Symbol literals begin with `#`, followed by an identifier. They have their own g
```cy
var currency = #usd
print(currency == #usd) -- 'true'
print float(currency) -- '123' or some arbitrary id.
print int(currency) -- '123' or some arbitrary id.
```
2 changes: 1 addition & 1 deletion docs/hugo/content/docs/toc/ffi.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,4 +112,4 @@ print ptr.value() --'3735928559'
### `type pointer`
| Method | Summary |
| ------------- | ----- |
| `value() float` | Returns the memory address as a `float`. |
| `value() int` | Returns the memory address as an `int`. The value may be negative since it's bitcasted from an unsigned 48-bit integer but it retains the original pointer bits. |
4 changes: 2 additions & 2 deletions docs/hugo/content/docs/toc/metaprogramming.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,8 @@ print boolean -- 'type: boolean'

### `type metatype`
```cy
func id(self) float
-- Returns the type ID as a float.
func id(self) int
-- Returns the type ID as an `int`.
```

## Annotations.
Expand Down
12 changes: 6 additions & 6 deletions docs/hugo/content/docs/toc/modules.md
Original file line number Diff line number Diff line change
Expand Up @@ -97,25 +97,25 @@ print contents

| Function | Summary |
| ------------- | ----- |
| `arrayFill(val any, n float) List` | Creates a list with initial capacity of `n` and values set to `val`. If the value is an object, it is shallow copied `n` times. |
| `arrayFill(val any, n int) List` | Creates a list with initial capacity of `n` and values set to `val`. If the value is an object, it is shallow copied `n` times. |
| `boolean(val any) boolean` | Converts a value to either `true` or `false`. |
| `cacheUrl(url string) string` | Returns the path of a locally cached file of `url`. If no such file exists locally, it's fetched from `url`. |
| `copy(val any) any` | Copies a primitive value or creates a shallow copy of an object value. |
| `error(e (enum \| symbol)) error` | Create an error from an enum or symbol. |
| `execCmd(args []string) Map{ out, err, exited }` | Runs a shell command and returns the stdout/stderr. |
| `exit(status float) noreturn` | Exits the program with a status code. |
| `exit(status int) noreturn` | Exits the program with a status code. |
| `evalJS(val string) none` | Evals JS from the host environment. This is only available in a web WASM build of Cyber. |
| `fetchUrl(url string) rawstring` | Fetches the contents at `url` using the HTTP GET request method. |
| `getInput() rawstring` | Reads stdin until a new line is reached. This is intended to read user input from the command line. For bulk reads from stdin, use `os.stdin`. |
| `int(val any) int` | Converts a value to an 32-bit integer. |
| `isAlpha(val float) boolean` | Returns whether a rune is an alphabetic letter. |
| `isDigit(val float) boolean` | Returns whether a rune is a digit. |
| `isAlpha(val int) boolean` | Returns whether a rune is an alphabetic letter. |
| `isDigit(val int) boolean` | Returns whether a rune is a digit. |
| `must(val any) any \| noreturn` | If `val` is an error, `panic(val)` is invoked. Otherwise, `val` is returned. |
| `float(val any) float` | Casts or converts the value to a `float`. Panics if type conversion fails. |
| `panic(e symbol) noreturn` | Stop execution in the current fiber and starts unwinding the call stack. See [Unexpected Errors]({{<relref "/docs/toc/errors#unexpected-errors">}}). |
| `parseCyber(src any) map` | Parses Cyber source string into structured map object. Currently, only metadata about static declarations is made available but this will be extended to include an AST. |
| `parseCyon(src any) any` | Parses a CYON string into a value. |
| `pointer(val any) pointer` | Converts a `float` to a `pointer` value, or casts to a `pointer`. This is usually used with FFI. |
| `pointer(val any) pointer` | Converts a `int` to a `pointer` value, or casts to a `pointer`. This is usually used with FFI. |
| `print(s string) none` | Prints a value as a string to stdout. The new line is also printed. |
| `prints(s string) none` | Prints a value as a string to stdout. |
| `rawstring(str string) rawstring` | Converts a string to a `rawstring`. |
Expand Down Expand Up @@ -229,7 +229,7 @@ for map each k, v:
| `fromCstr(pointer) rawstring` | Returns a `rawstring` from a null terminated C string. |
| `getEnv(key any) string \| none` | Returns an environment value by key. |
| `getEnvAll() Map` | Returns all environment entries as a `Map`. |
| `malloc(size float) pointer` | Allocates `size` bytes of memory and returns a pointer. |
| `malloc(size int) pointer` | Allocates `size` bytes of memory and returns a pointer. |
| `milliTime() float` | Return the calendar timestamp, in milliseconds, relative to UTC 1970-01-01. |
| `openDir(path any) Dir \| error` | Invokes `openDir(path, false)`. |
| `openDir(path any, iterable boolean) Dir \| error` | Opens a directory at the given `path`. `iterable` indicates that the directory's entries can be iterated. |
Expand Down
8 changes: 7 additions & 1 deletion src/api.zig
Original file line number Diff line number Diff line change
Expand Up @@ -347,12 +347,18 @@ pub const UserVM = struct {
vm.framePtr = vm.stack.ptr + framePtr;

self.retain(func);
defer self.release(func);
vm.framePtr[4 + args.len] = func;
for (args, 0..) |arg, i| {
self.retain(arg);
vm.framePtr[4 + i] = arg;
}
defer {
self.release(func);
for (args) |arg| {
self.release(arg);
}
}

const retInfo = cy.vm.buildReturnInfo(1, false, 0);
try cy.vm.callNoInline(vm, &vm.pc, &vm.framePtr, func, 0, @intCast(args.len), retInfo);
try @call(.never_inline, cy.vm.evalLoopGrowStack, .{vm});
Expand Down
23 changes: 10 additions & 13 deletions src/arc.zig
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ pub fn release(vm: *cy.VM, val: cy.Value) linksection(cy.HotSection) void {
}
if (val.isPointer()) {
const obj = val.asHeapObject();
log.tracev("release obj: {}, rc={}", .{val.getUserTag(), obj.head.rc});
if (cy.Trace) {
checkDoubleFree(vm, obj);
}
obj.head.rc -= 1;
log.tracev("release {} rc={}", .{val.getUserTag(), obj.head.rc});
if (cy.TrackGlobalRC) {
if (cy.Trace) {
if (vm.refCounts == 0) {
Expand All @@ -35,6 +35,8 @@ pub fn release(vm: *cy.VM, val: cy.Value) linksection(cy.HotSection) void {
if (obj.head.rc == 0) {
@call(.never_inline, cy.heap.freeObject, .{vm, obj});
}
} else {
log.tracev("release: {}, nop", .{val.getUserTag()});
}
}

Expand Down Expand Up @@ -83,18 +85,13 @@ pub fn releaseObject(vm: *cy.VM, obj: *cy.HeapObject) linksection(cy.HotSection)
}
}

pub fn runTempReleaseOps(vm: *cy.VM, stack: []const cy.Value, framePtr: usize, startPc: usize) void {
if (vm.ops[startPc].opcode() == .release) {
var pc = startPc;
while (true) {
const local = vm.ops[pc+1].val;
// stack[framePtr + local].dump();
release(vm, stack[framePtr + local]);
pc += 2;
if (vm.ops[pc].opcode() != .release) {
break;
}
}
pub fn runTempReleaseOps(vm: *cy.VM, fp: [*]const cy.Value, tempIdx: u32) void {
log.tracev("unwind release temps", .{});
var curIdx = tempIdx;
while (curIdx != cy.NullId) {
log.tracev("unwind release: {}", .{vm.unwindTempRegs[curIdx]});
release(vm, fp[vm.unwindTempRegs[curIdx]]);
curIdx = vm.unwindTempPrevIndexes[curIdx];
}
}

Expand Down
Loading

0 comments on commit b2b8d03

Please sign in to comment.