diff --git a/README.md b/README.md index 071244d..63f0017 100644 --- a/README.md +++ b/README.md @@ -5,7 +5,7 @@ language that cross-compiles to C. Tomo is designed to anticipate and influence the language design decisions of the future. ``` -func greeting(name:Text, add_exclamation:Bool)->Text: +func greeting(name:Text, add_exclamation:Bool -> Text): message := "hello $name" message = " ":join([w:title() for w in message:split($/{space}/)]) if add_exclamation: diff --git a/ast.c b/ast.c index 21b31fc..af0aea5 100644 --- a/ast.c +++ b/ast.c @@ -130,7 +130,8 @@ CORD ast_to_xml(ast_t *ast) optional_tagged("filter", data.filter)) T(FunctionDef, "%r%r%r", ast_to_xml(data.name), arg_list_to_xml(data.args), optional_tagged_type("return-type", data.ret_type), ast_to_xml(data.body)) - T(Lambda, "%r%r)", arg_list_to_xml(data.args), ast_to_xml(data.body)) + T(Lambda, "%r%r%r)", arg_list_to_xml(data.args), + optional_tagged_type("return-type", data.ret_type), ast_to_xml(data.body)) T(FunctionCall, "%r%r", ast_to_xml(data.fn), arg_list_to_xml(data.args)) T(MethodCall, "%r%s%r", ast_to_xml(data.self), data.name, arg_list_to_xml(data.args)) T(Block, "%r", ast_list_to_xml(data.statements)) diff --git a/ast.h b/ast.h index 5659f64..4b8e03d 100644 --- a/ast.h +++ b/ast.h @@ -233,6 +233,7 @@ struct ast_s { } FunctionDef; struct { arg_ast_t *args; + type_ast_t *ret_type; ast_t *body; int64_t id; } Lambda; diff --git a/compile.c b/compile.c index ab596e8..117a65a 100644 --- a/compile.c +++ b/compile.c @@ -2519,6 +2519,16 @@ CORD compile(env_t *env, ast_t *ast) type_t *ret_t = get_type(body_scope, lambda->body); if (ret_t->tag == ReturnType) ret_t = Match(ret_t, ReturnType)->ret; + + if (lambda->ret_type) { + type_t *declared = parse_type_ast(env, lambda->ret_type); + if (can_promote(ret_t, declared)) + ret_t = declared; + else + code_err(ast, "This function was declared to return a value of type %T, but actually returns a value of type %T", + declared, ret_t); + } + fn_ctx.return_type = ret_t; if (env->fn_ctx->closed_vars) { diff --git a/docs/README.md b/docs/README.md index c58c5c8..e444936 100644 --- a/docs/README.md +++ b/docs/README.md @@ -44,7 +44,7 @@ Gets a line of user input text with a prompt. **Usage:** ```markdown -ask(prompt:Text, bold:Bool = yes, force_tty:Bool = yes) -> Void +ask(prompt:Text, bold:Bool = yes, force_tty:Bool = yes -> Void) ``` **Parameters:** @@ -79,7 +79,7 @@ Exits the program with a given status and optionally prints a message. **Usage:** ```markdown -ask(message:Text? = !Text, status:Int32 = 1[32]) -> Void +ask(message:Text? = !Text, status:Int32 = 1[32] -> Void) ``` **Parameters:** @@ -106,7 +106,7 @@ Prints a message to the console. **Usage:** ```markdown -say(text:Text, newline:Bool = yes) -> Void +say(text:Text, newline:Bool = yes -> Void) ``` **Parameters:** @@ -132,7 +132,7 @@ Pause execution for a given number of seconds. **Usage:** ```markdown -sleep(seconds: Num) -> Void +sleep(seconds: Num -> Void) ``` **Parameters:** @@ -156,7 +156,7 @@ Prints a message to the console, aborts the program, and prints a stack trace. **Usage:** ```markdown -fail(message:Text) -> Abort +fail(message:Text -> Abort) ``` **Parameters:** @@ -180,7 +180,7 @@ Gets the current time. This is an alias for `DateTime.now()`. **Usage:** ```markdown -now() -> DateTime +now(->DateTime) ``` **Parameters:** diff --git a/docs/arrays.md b/docs/arrays.md index edde43a..773500a 100644 --- a/docs/arrays.md +++ b/docs/arrays.md @@ -239,7 +239,7 @@ Performs a binary search on a sorted array. **Usage:** ```markdown -binary_search(arr: [T], by=T.compare) -> Int +binary_search(arr: [T], by=T.compare -> Int) ``` **Parameters:** @@ -275,7 +275,7 @@ Creates a new array with elements spaced by the specified step value. **Usage:** ```markdown -by(arr: [T], step: Int) -> [T] +by(arr: [T], step: Int -> [T]) ``` **Parameters:** @@ -301,7 +301,7 @@ Clears all elements from the array. **Usage:** ```markdown -clear(arr: & [T]) -> Void +clear(arr: & [T] -> Void) ``` **Parameters:** @@ -325,7 +325,7 @@ Counts the occurrences of each element in the array. **Usage:** ```markdown -counts(arr: [T]) -> {T: Int} +counts(arr: [T] -> {T: Int}) ``` **Parameters:** @@ -350,7 +350,7 @@ Finds the index of the first occurrence of an element (if any). **Usage:** ```markdown -find(arr: [T]) -> Int? +find(arr: [T] -> Int?) ``` **Parameters:** @@ -378,7 +378,7 @@ Find the index of the first item that matches a predicate function (if any). **Usage:** ```markdown -first(arr: [T], predicate: func(item:&T)->Bool) -> Int +first(arr: [T], predicate: func(item:&T)->Bool -> Int) ``` **Parameters:** @@ -408,7 +408,7 @@ Returns a slice of the array starting from a specified index. **Usage:** ```markdown -from(arr: [T], first: Int) -> [T] +from(arr: [T], first: Int -> [T]) ``` **Parameters:** @@ -434,7 +434,7 @@ Checks if the array has any elements. **Usage:** ```markdown -has(arr: [T]) -> Bool +has(arr: [T] -> Bool) ``` **Parameters:** @@ -460,7 +460,7 @@ Removes and returns the top element of a heap. By default, this is the **Usage:** ```markdown -heap_pop(arr: & [T], by=T.compare) -> T +heap_pop(arr: & [T], by=T.compare -> T) ``` **Parameters:** @@ -490,7 +490,7 @@ is a *minimum* heap. **Usage:** ```markdown -heap_push(arr: & [T], item: T, by=T.compare) -> Void +heap_push(arr: & [T], item: T, by=T.compare -> Void) ``` **Parameters:** @@ -517,7 +517,7 @@ Converts an array into a heap. **Usage:** ```markdown -heapify(arr: & [T], by=T.compare) -> Void +heapify(arr: & [T], by=T.compare -> Void) ``` **Parameters:** @@ -544,7 +544,7 @@ Inserts an element at a specified position in the array. **Usage:** ```markdown -insert(arr: & [T], item: T, at: Int = 0) -> Void +insert(arr: & [T], item: T, at: Int = 0 -> Void) ``` **Parameters:** @@ -579,7 +579,7 @@ Inserts an array of items at a specified position in the array. **Usage:** ```markdown -insert_all(arr: & [T], items: [T], at: Int = 0) -> Void +insert_all(arr: & [T], items: [T], at: Int = 0 -> Void) ``` **Parameters:** @@ -614,7 +614,7 @@ Selects a random element from the array. **Usage:** ```markdown -random(arr: [T]) -> T +random(arr: [T] -> T) ``` **Parameters:** @@ -639,7 +639,7 @@ Removes elements from the array starting at a specified index. **Usage:** ```markdown -remove_at(arr: & [T], at: Int = -1, count: Int = 1) -> Void +remove_at(arr: & [T], at: Int = -1, count: Int = 1 -> Void) ``` **Parameters:** @@ -672,7 +672,7 @@ Removes all occurrences of a specified item from the array. **Usage:** ```markdown -remove_item(arr: & [T], item: T, max_count: Int = -1) -> Void +remove_item(arr: & [T], item: T, max_count: Int = -1 -> Void) ``` **Parameters:** @@ -705,7 +705,7 @@ Returns a reversed slice of the array. **Usage:** ```markdown -reversed(arr: [T]) -> [T] +reversed(arr: [T] -> [T]) ``` **Parameters:** @@ -731,7 +731,7 @@ probabilities. **Usage:** ```markdown -sample(arr: [T], count: Int, weights: [Num]? = ![Num]) -> [T] +sample(arr: [T], count: Int, weights: [Num]? = ![Num] -> [T]) ``` **Parameters:** @@ -769,7 +769,7 @@ Shuffles the elements of the array in place. **Usage:** ```markdown -shuffle(arr: & [T]) -> Void +shuffle(arr: & [T] -> Void) ``` **Parameters:** @@ -793,7 +793,7 @@ Creates a new array with elements shuffled. **Usage:** ```markdown -shuffled(arr: [T]) -> [T] +shuffled(arr: [T] -> [T]) ``` **Parameters:** @@ -818,7 +818,7 @@ Sorts the elements of the array in place in ascending order (small to large). **Usage:** ```markdown -sort(arr: & [T], by=T.compare) -> Void +sort(arr: & [T], by=T.compare -> Void) ``` **Parameters:** @@ -851,7 +851,7 @@ Creates a new array with elements sorted. **Usage:** ```markdown -sorted(arr: [T], by=T.compare) -> [T] +sorted(arr: [T], by=T.compare -> [T]) ``` **Parameters:** @@ -881,7 +881,7 @@ Returns a slice of the array from the start of the original array up to a specif **Usage:** ```markdown -to(arr: [T], last: Int) -> [T] +to(arr: [T], last: Int -> [T]) ``` **Parameters:** @@ -910,7 +910,7 @@ Returns a Set that contains the unique elements of the array. **Usage:** ```markdown -unique(arr: [T]) -> {T} +unique(arr: [T] -> {T}) ``` **Parameters:** diff --git a/docs/booleans.md b/docs/booleans.md index 7d2c29a..7525966 100644 --- a/docs/booleans.md +++ b/docs/booleans.md @@ -16,7 +16,7 @@ boolean values are case-insensitive variations of `yes`/`no`, `y`/`n`, **Usage:** ```tomo -from_text(text: Text, success: Bool = !&Bool) -> Bool +from_text(text: Text, success: Bool = !&Bool -> Bool) ``` **Parameters:** @@ -49,7 +49,7 @@ Generates a random boolean value based on a specified probability. **Usage:** ```tomo -random(p: Float = 0.5) -> Bool +random(p: Float = 0.5 -> Bool) ``` **Parameters:** diff --git a/docs/bytes.md b/docs/bytes.md index 3618042..579db9d 100644 --- a/docs/bytes.md +++ b/docs/bytes.md @@ -16,7 +16,7 @@ Generates a random byte value in the specified range. **Usage:** ```tomo -random(min: Byte = Byte.min, max: Byte = Byte.max) -> Byte +random(min: Byte = Byte.min, max: Byte = Byte.max -> Byte) ``` **Parameters:** diff --git a/docs/channels.md b/docs/channels.md index 8763f11..47b9ced 100644 --- a/docs/channels.md +++ b/docs/channels.md @@ -31,7 +31,7 @@ Adds an item to the channel. **Usage:** ```markdown -give(channel:|T|, item: T, front: Bool = no) -> Void +give(channel:|T|, item: T, front: Bool = no -> Void) ``` **Parameters:** @@ -57,7 +57,7 @@ Adds multiple items to the channel. **Usage:** ```markdown -give_all(channel:|T|, items: [T], front: Bool = no) -> Void +give_all(channel:|T|, items: [T], front: Bool = no -> Void) ``` **Parameters:** @@ -83,7 +83,7 @@ Removes and returns an item from the channel. If the channel is empty, it waits **Usage:** ```markdown -get(channel:|T|, front: Bool = yes) -> T +get(channel:|T|, front: Bool = yes -> T) ``` **Parameters:** @@ -110,7 +110,7 @@ it. If the channel is empty, it waits until an item is available. **Usage:** ```markdown -peek(channel:|T|, front: Bool = yes) -> T +peek(channel:|T|, front: Bool = yes -> T) ``` **Parameters:** @@ -136,7 +136,7 @@ Removes all items from the channel. **Usage:** ```markdown -clear(channel:|T|) -> Void +clear(channel:|T| -> Void) ``` **Parameters:** @@ -160,7 +160,7 @@ Returns a list of all items currently in the channel without removing them. **Usage:** ```markdown -channel:view() -> [T] +channel:view(->[T]) ``` **Parameters:** diff --git a/docs/datetime.md b/docs/datetime.md index dd02b20..9d4e1e4 100644 --- a/docs/datetime.md +++ b/docs/datetime.md @@ -79,7 +79,7 @@ calculated. **Usage:** ```markdown -datetime:after(seconds : Num = 0.0, minutes : Num = 0.0, hours : Num = 0.0, days : Int = 0, weeks : Int = 0, months : Int = 0, years : Int = 0, timezone : Text? = !Text) -> DateTime +datetime:after(seconds : Num = 0.0, minutes : Num = 0.0, hours : Num = 0.0, days : Int = 0, weeks : Int = 0, months : Int = 0, years : Int = 0, timezone : Text? = !Text -> DateTime) ``` **Parameters:** @@ -113,7 +113,7 @@ specifier, which gives the date in `YYYY-MM-DD` form. **Usage:** ```markdown -datetime:date(timezone : Text? = !Text) -> Text +datetime:date(timezone : Text? = !Text -> Text) ``` **Parameters:** @@ -141,7 +141,7 @@ timezone. **Usage:** ```markdown -datetime:format(format: Text = "%Y-%m-%dT%H:%M:%S%z", timezone : Text? = !Text) -> Text +datetime:format(format: Text = "%Y-%m-%dT%H:%M:%S%z", timezone : Text? = !Text -> Text) ``` **Parameters:** @@ -168,7 +168,7 @@ the given UNIX epoch timestamp (seconds since January 1, 1970 UTC). **Usage:** ```markdown -DateTime.from_unix_timestamp(timestamp: Int64) -> DateTime +DateTime.from_unix_timestamp(timestamp: Int64 -> DateTime) ``` **Parameters:** @@ -195,7 +195,7 @@ provided optional fields. **Usage:** ```markdown -datetime:get(year : &Int? = !&Int, month : &Int? = !&Int, day : &Int? = !&Int, hour : &Int? = !&Int, minute : &Int? = !&Int, second : &Int? = !&Int, nanosecond : &Int? = !&Int, weekday : &Int? = !&Int, timezone : Text? = !Text) -> Void +datetime:get(year : &Int? = !&Int, month : &Int? = !&Int, day : &Int? = !&Int, hour : &Int? = !&Int, minute : &Int? = !&Int, second : &Int? = !&Int, nanosecond : &Int? = !&Int, weekday : &Int? = !&Int, timezone : Text? = !Text -> Void) ``` **Parameters:** @@ -233,7 +233,7 @@ calling `DateTime.set_local_timezone(...)`. **Usage:** ```markdown -DateTime.get_local_timezone() -> Text +DateTime.get_local_timezone(->Text) ``` **Parameters:** @@ -258,7 +258,7 @@ Return the number of hours until a given datetime. **Usage:** ```markdown -datetime:hours_till(then:DateTime) -> Num +datetime:hours_till(then:DateTime -> Num) ``` **Parameters:** @@ -284,7 +284,7 @@ Return the number of minutes until a given datetime. **Usage:** ```markdown -datetime:minutes_till(then:DateTime) -> Num +datetime:minutes_till(then:DateTime -> Num) ``` **Parameters:** @@ -312,7 +312,7 @@ constructor. **Usage:** ```markdown -DateTime.new(year : Int, month : Int, day : Int, hour : Int = 0, minute : Int = 0, second : Num = 0.0) -> DateTime +DateTime.new(year : Int, month : Int, day : Int, hour : Int = 0, minute : Int = 0, second : Num = 0.0 -> DateTime) ``` **Parameters:** @@ -351,7 +351,7 @@ is the same as the global function `now()`. **Usage:** ```markdown -DateTime.now() -> DateTime +DateTime.now(->DateTime) ``` **Parameters:** @@ -377,7 +377,7 @@ or a null value if the value could not be successfully parsed. **Usage:** ```markdown -DateTime.parse(text: Text, format: Text = "%Y-%m-%dT%H:%M:%S%z") -> DateTime? +DateTime.parse(text: Text, format: Text = "%Y-%m-%dT%H:%M:%S%z" -> DateTime?) ``` **Parameters:** @@ -410,7 +410,7 @@ between two `DateTime`s. For example: `5 minutes ago` or `1 day later` **Usage:** ```markdown -datetime:relative(relative_to : DateTime = DateTime.now(), timezone : Text? = !Text) -> Text +datetime:relative(relative_to : DateTime = DateTime.now(), timezone : Text? = !Text -> Text) ``` **Parameters:** @@ -445,7 +445,7 @@ Return the number of seconds until a given datetime. **Usage:** ```markdown -datetime:seconds_till(then:DateTime) -> Num +datetime:seconds_till(then:DateTime -> Num) ``` **Parameters:** @@ -475,7 +475,7 @@ converted to text. **Usage:** ```markdown -DateTime.set_local_timezone(timezone : Text? = !Text) -> Void +DateTime.set_local_timezone(timezone : Text? = !Text -> Void) ``` **Parameters:** @@ -501,7 +501,7 @@ Return a text representation of the time component of the given datetime. **Usage:** ```markdown -datetime:time(seconds : Bool = no, am_pm : Bool = yes, timezone : Text? = !Text) -> Text +datetime:time(seconds : Bool = no, am_pm : Bool = yes, timezone : Text? = !Text -> Text) ``` **Parameters:** @@ -537,7 +537,7 @@ January 1, 1970 UTC). **Usage:** ```markdown -datetime:unix_timestamp() -> Int64 +datetime:unix_timestamp(->Int64) ``` **Parameters:** diff --git a/docs/enums.md b/docs/enums.md index 4123fbc..c73379f 100644 --- a/docs/enums.md +++ b/docs/enums.md @@ -54,7 +54,7 @@ from a function with an explicit return type: enum ArgumentType(AnInt(x:Int), SomeText(text:Text)) enum ReturnType(Nothing, AnInt(x:Int)) -func increment(arg:ArgumentType)->ReturnType: +func increment(arg:ArgumentType -> ReturnType): when arg is AnInt(x): return AnInt(x + 1) is SomeText: diff --git a/docs/functions.md b/docs/functions.md index 61a1003..174ad23 100644 --- a/docs/functions.md +++ b/docs/functions.md @@ -3,7 +3,7 @@ In Tomo, you can define functions with the `func` keyword: ```tomo -func add(x:Int, y:Int)->Int: +func add(x:Int, y:Int -> Int): return x + y ``` @@ -11,7 +11,7 @@ Functions require you to explicitly write out the types of each argument and the return type of the function (unless the function doesn't return any values). For convenience, you can lump arguments with the same type together to avoid -having to retype the same type name: `func add(x, y:Int)->Int` +having to retype the same type name: `func add(x, y:Int -> Int)` ## Default Arguments @@ -19,7 +19,7 @@ Instead of giving a type, you can provide a default argument and the type checker will infer the type of the argument from that value: ```tomo -func increment(x:Int, amount=1)->Int: +func increment(x:Int, amount=1 -> Int): return x + amount ``` @@ -35,7 +35,7 @@ callsite: ``` **Note:** Default arguments are re-evaluated at the callsite for each function -call, so if your default argument is `func foo(x=Int.random(1,10))->Int`, then +call, so if your default argument is `func foo(x=Int.random(1,10) -> Int)`, then each time you call the function without an `x` argument, it will give you a new random number. @@ -68,7 +68,7 @@ Tomo supports automatic function caching using the `cached` or `cache_size=N` attributes on a function definition: ```tomo -func add(x, y:Int; cached)->Int: +func add(x, y:Int -> Int; cached): return x + y ``` @@ -78,13 +78,13 @@ return value for those arguments. The above example is functionally similar to the following code: ```tomo -func _add(x, y:Int)->Int: +func _add(x, y:Int -> Int): return x + y struct add_args(x,y:Int) add_cache := @{:add_args:Int} -func add(x, y:Int)->Int: +func add(x, y:Int -> Int): args := add_args(x, y) if add_cache:has(args): return add_cache:get(args) @@ -98,7 +98,7 @@ evicted if the cache has reached the maximum size and needs to insert a new entry: ```tomo -func doop(x:Int, y:Text, z:[Int]; cache_size=100)->Text: +func doop(x:Int, y:Text, z:[Int]; cache_size=100 -> Text): return "x=$x y=$y z=$z" ``` @@ -108,7 +108,7 @@ Functions can also be given an `inline` attribute, which encourages the compiler to inline the function when possible: ```tomo -func add(x, y:Int; inline)->Int: +func add(x, y:Int -> Int; inline): return x + y ``` @@ -137,7 +137,10 @@ fn := func(x,y:Int): Lambda functions must declare the types of their arguments, but do not require declaring the return type. Because lambdas cannot be recursive or corecursive (since they aren't declared with a name), it is always possible to infer the -return type without much difficulty. +return type without much difficulty. If you do choose to declare a return type, +the compiler will attempt to promote return values to that type, or give a +compiler error if the return value is not compatible with the declared return +type. ## Closures @@ -148,7 +151,7 @@ values. **Captured values are copied to a new location at the moment the lambda is created and will not reflect changes to local variables.** ```tomo -func create_adder(n:Int) -> func(i:Int)->Int: +func create_adder(n:Int -> func(i:Int -> Int)): adder := func(i:Int): return n + i diff --git a/docs/integers.md b/docs/integers.md index 1b25bcf..36dac3c 100644 --- a/docs/integers.md +++ b/docs/integers.md @@ -37,7 +37,7 @@ Formats an integer as a string with a specified number of digits. **Usage:** ```tomo -format(i: Int, digits: Int = 0) -> Text +format(i: Int, digits: Int = 0 -> Text) ``` **Parameters:** @@ -63,7 +63,7 @@ Converts an integer to its hexadecimal representation. **Usage:** ```tomo -hex(i: Int, digits: Int = 0, uppercase: Bool = yes, prefix: Bool = yes) -> Text +hex(i: Int, digits: Int = 0, uppercase: Bool = yes, prefix: Bool = yes -> Text) ``` **Parameters:** @@ -91,7 +91,7 @@ Converts an integer to its octal representation. **Usage:** ```tomo -octal(i: Int, digits: Int = 0, prefix: Bool = yes) -> Text +octal(i: Int, digits: Int = 0, prefix: Bool = yes -> Text) ``` **Parameters:** @@ -118,7 +118,7 @@ Generates a random integer between the specified minimum and maximum values. **Usage:** ```tomo -random(min: Int, max: Int) -> Int +random(min: Int, max: Int -> Int) ``` **Parameters:** @@ -144,7 +144,7 @@ Converts a text representation of an integer into an integer. **Usage:** ```tomo -from_text(text: Text, success: Bool = !&Bool?) -> Int +from_text(text: Text, success: Bool = !&Bool? -> Int) ``` **Parameters:** @@ -188,7 +188,7 @@ Creates an inclusive range of integers between the specified start and end value **Usage:** ```tomo -to(from: Int, to: Int) -> Range +to(from: Int, to: Int -> Range) ``` **Parameters:** @@ -214,7 +214,7 @@ Calculates the absolute value of an integer. **Usage:** ```tomo -abs(x: Int) -> Int +abs(x: Int -> Int) ``` **Parameters:** @@ -239,7 +239,7 @@ Calculates the square root of an integer. **Usage:** ```tomo -sqrt(x: Int) -> Int +sqrt(x: Int -> Int) ``` **Parameters:** @@ -272,7 +272,7 @@ for more details. **Usage:** ```tomo -is_prime(x: Int, reps: Int = 50) -> Bool +is_prime(x: Int, reps: Int = 50 -> Bool) ``` **Parameters:** @@ -306,7 +306,7 @@ for more details. **Usage:** ```tomo -next_prime(x: Int) -> Int +next_prime(x: Int -> Int) ``` **Parameters:** @@ -339,7 +339,7 @@ for more details. **Usage:** ```tomo -prev_prime(x: Int) -> Int +prev_prime(x: Int -> Int) ``` **Parameters:** @@ -365,7 +365,7 @@ that range. **Usage:** ```tomo -clamped(x, low, high: Int) -> Int +clamped(x, low, high: Int -> Int) ``` **Parameters:** diff --git a/docs/langs.md b/docs/langs.md index 0eecb3c..31ce275 100644 --- a/docs/langs.md +++ b/docs/langs.md @@ -10,7 +10,7 @@ where a different type of string is needed. ```tomo lang HTML: - func escape(t:Text)->HTML: + func escape(t:Text -> HTML): t = t:replace_all({ $/&/: "&", $/HTML: + func paragraph(content:HTML -> HTML): return $HTML"

$content

" ``` @@ -74,10 +74,10 @@ instead of building a global function called `execute()` that takes a ```tomo lang Sh: - func escape(text:Text)->Sh: + func escape(text:Text -> Sh): return Sh.without_escaping("'" ++ text:replace($/'/, "''") ++ "'") - func execute(sh:Sh)->Text: + func execute(sh:Sh -> Text): ... dir := ask("List which dir? ") diff --git a/docs/metamethods.md b/docs/metamethods.md index 8ab2be4..dbd1106 100644 --- a/docs/metamethods.md +++ b/docs/metamethods.md @@ -3,25 +3,25 @@ This language relies on a small set of "metamethods" which define special behavior that is required for all types: -- `as_text(obj:&(optional)T, colorize=no, type:&TypeInfo_t)->Text`: a method to +- `func as_text(obj:&(optional)T, colorize=no, type:&TypeInfo_t -> Text)`: a method to convert the type to a string. If `colorize` is `yes`, then the method should include ANSI escape codes for syntax highlighting. If the `obj` pointer is `NULL`, a string representation of the type will be returned instead. -- `compare(x:&T, y:&T, type:&TypeInfo_t)->Int32`: Return an integer representing +- `func compare(x:&T, y:&T, type:&TypeInfo_t -> Int32)`: Return an integer representing the result of comparing `x` and `y`, where negative numbers mean `x` is less than `y`, zero means `x` is equal to `y`, and positive numbers mean `x` is greater than `y`. For the purpose of floating point numbers, `NaN` is sorted as greater than any other number value and `NaN` values are compared bitwise between each other. -- `equals(x:&T, y:&T, type:&TypeInfo_t)->Bool`: This is the same as comparing two +- `func equals(x:&T, y:&T, type:&TypeInfo_t -> Bool)`: This is the same as comparing two numbers to check for zero, except for some minor differences: floating point `NaN` values are _not_ equal to each other (IEEE 754) and the implementation of `equals` may be faster to compute than `compare` for certain types, such as tables. -- `hash(x:&T, type:&TypeInfo_t)->Int32`: Values are hashed when used as keys in a +- `func hash(x:&T, type:&TypeInfo_t -> Int32)`: Values are hashed when used as keys in a table or set. Hashing is consistent with equality, so two values that are equal _must_ hash to the same hash value, ideally in a way that makes it unlikely that two different values will have the same hash value. diff --git a/docs/namespacing.md b/docs/namespacing.md index 86b24ce..5863841 100644 --- a/docs/namespacing.md +++ b/docs/namespacing.md @@ -17,7 +17,7 @@ my_var := 123 struct Baz(x:Int): member := 5 - func frob(b:Baz)->Int: + func frob(b:Baz -> Int): return b.x ``` diff --git a/docs/nums.md b/docs/nums.md index 151a0aa..577225b 100644 --- a/docs/nums.md +++ b/docs/nums.md @@ -42,7 +42,7 @@ Calculates the absolute value of a number. **Usage:** ```tomo -abs(n: Num) -> Num +abs(n: Num -> Num) ``` **Parameters:** @@ -67,7 +67,7 @@ Computes the arc cosine of a number. **Usage:** ```tomo -acos(x: Num) -> Num +acos(x: Num -> Num) ``` **Parameters:** @@ -92,7 +92,7 @@ Computes the inverse hyperbolic cosine of a number. **Usage:** ```tomo -acosh(x: Num) -> Num +acosh(x: Num -> Num) ``` **Parameters:** @@ -117,7 +117,7 @@ Computes the arc sine of a number. **Usage:** ```tomo -asin(x: Num) -> Num +asin(x: Num -> Num) ``` **Parameters:** @@ -142,7 +142,7 @@ Computes the inverse hyperbolic sine of a number. **Usage:** ```tomo -asinh(x: Num) -> Num +asinh(x: Num -> Num) ``` **Parameters:** @@ -167,7 +167,7 @@ Computes the arc tangent of the quotient of two numbers. **Usage:** ```tomo -atan2(x: Num, y: Num) -> Num +atan2(x: Num, y: Num -> Num) ``` **Parameters:** @@ -193,7 +193,7 @@ Computes the arc tangent of a number. **Usage:** ```tomo -atan(x: Num) -> Num +atan(x: Num -> Num) ``` **Parameters:** @@ -218,7 +218,7 @@ Computes the inverse hyperbolic tangent of a number. **Usage:** ```tomo -atanh(x: Num) -> Num +atanh(x: Num -> Num) ``` **Parameters:** @@ -243,7 +243,7 @@ Computes the cube root of a number. **Usage:** ```tomo -cbrt(x: Num) -> Num +cbrt(x: Num -> Num) ``` **Parameters:** @@ -268,7 +268,7 @@ Rounds a number up to the nearest integer. **Usage:** ```tomo -ceil(x: Num) -> Num +ceil(x: Num -> Num) ``` **Parameters:** @@ -293,7 +293,7 @@ Copies the sign of one number to another. **Usage:** ```tomo -copysign(x: Num, y: Num) -> Num +copysign(x: Num, y: Num -> Num) ``` **Parameters:** @@ -319,7 +319,7 @@ Computes the cosine of a number (angle in radians). **Usage:** ```tomo -cos(x: Num) -> Num +cos(x: Num -> Num) ``` **Parameters:** @@ -344,7 +344,7 @@ Computes the hyperbolic cosine of a number. **Usage:** ```tomo -cosh(x: Num) -> Num +cosh(x: Num -> Num) ``` **Parameters:** @@ -369,7 +369,7 @@ Computes the error function of a number. **Usage:** ```tomo -erf(x: Num) -> Num +erf(x: Num -> Num) ``` **Parameters:** @@ -394,7 +394,7 @@ Computes the complementary error function of a number. **Usage:** ```tomo -erfc(x: Num) -> Num +erfc(x: Num -> Num) ``` **Parameters:** @@ -419,7 +419,7 @@ Computes \( 2^x \) for a number. **Usage:** ```tomo -exp2(x: Num) -> Num +exp2(x: Num -> Num) ``` **Parameters:** @@ -444,7 +444,7 @@ Computes the exponential function \( e^x \) for a number. **Usage:** ```tomo -exp(x: Num) -> Num +exp(x: Num -> Num) ``` **Parameters:** @@ -469,7 +469,7 @@ Computes \( e^x - 1 \) for a number. **Usage:** ```tomo -expm1(x: Num) -> Num +expm1(x: Num -> Num) ``` **Parameters:** @@ -494,7 +494,7 @@ Computes the positive difference between two numbers. **Usage:** ```tomo -fdim(x: Num, y: Num) -> Num +fdim(x: Num, y: Num -> Num) ``` **Parameters:** @@ -522,7 +522,7 @@ Rounds a number down to the nearest integer. **Usage:** ```tomo -floor(x: Num) -> Num +floor(x: Num -> Num) ``` **Parameters:** @@ -547,7 +547,7 @@ Formats a number as a string with a specified precision. **Usage:** ```tomo -format(n: Num, precision: Int = 0) -> Text +format(n: Num, precision: Int = 0 -> Text) ``` **Parameters:** @@ -573,7 +573,7 @@ Converts a string representation of a number into a floating-point number. **Usage:** ```tomo -from_text(text: Text, the_rest: Text = "!&Text") -> Num +from_text(text: Text, the_rest: Text = "!&Text" -> Num) ``` **Parameters:** @@ -601,7 +601,7 @@ Computes the Euclidean norm, \( \sqrt{x^2 + y^2} \), of two numbers. **Usage:** ```tomo -hypot(x: Num, y: Num) -> Num +hypot(x: Num, y: Num -> Num) ``` **Parameters:** @@ -627,7 +627,7 @@ Checks if a number is finite. **Usage:** ```tomo -isfinite(n: Num) -> Bool +isfinite(n: Num -> Bool) ``` **Parameters:** @@ -654,7 +654,7 @@ Checks if a number is infinite. **Usage:** ```tomo -isinf(n: Num) -> Bool +isinf(n: Num -> Bool) ``` **Parameters:** @@ -681,7 +681,7 @@ Checks if a number is NaN (Not a Number). **Usage:** ```tomo -isnan(n: Num) -> Bool +isnan(n: Num -> Bool) ``` **Parameters:** @@ -708,7 +708,7 @@ Computes the Bessel function of the first kind of order 0. **Usage:** ```tomo -j0(x: Num) -> Num +j0(x: Num -> Num) ``` **Parameters:** @@ -733,7 +733,7 @@ Computes the Bessel function of the first kind of order 1. **Usage:** ```tomo -j1(x: Num) -> Num +j1(x: Num -> Num) ``` **Parameters:** @@ -758,7 +758,7 @@ Computes the base-10 logarithm of a number. **Usage:** ```tomo -log10(x: Num) -> Num +log10(x: Num -> Num) ``` **Parameters:** @@ -783,7 +783,7 @@ Computes \( \log(1 + x) \) for a number. **Usage:** ```tomo -log1p(x: Num) -> Num +log1p(x: Num -> Num) ``` **Parameters:** @@ -808,7 +808,7 @@ Computes the base-2 logarithm of a number. **Usage:** ```tomo -log2(x: Num) -> Num +log2(x: Num -> Num) ``` **Parameters:** @@ -833,7 +833,7 @@ Computes the natural logarithm (base \( e \)) of a number. **Usage:** ```tomo -log(x: Num) -> Num +log(x: Num -> Num) ``` **Parameters:** @@ -858,7 +858,7 @@ Computes the binary exponent (base-2 logarithm) of a number. **Usage:** ```tomo -logb(x: Num) -> Num +logb(x: Num -> Num) ``` **Parameters:** @@ -883,7 +883,7 @@ Interpolates between two numbers based on a given amount. **Usage:** ```tomo -mix(amount: Num, x: Num, y: Num) -> Num +mix(amount: Num, x: Num, y: Num -> Num) ``` **Parameters:** @@ -912,7 +912,7 @@ Generates a NaN (Not a Number) value. **Usage:** ```tomo -nan(tag: Text = "") -> Num +nan(tag: Text = "" -> Num) ``` **Parameters:** @@ -939,7 +939,7 @@ small enough, they are considered near each other. **Usage:** ```tomo -near(x: Num, y: Num, ratio: Num = 1e-9, min_epsilon: Num = 1e-9) -> Bool +near(x: Num, y: Num, ratio: Num = 1e-9, min_epsilon: Num = 1e-9 -> Bool) ``` **Parameters:** @@ -973,7 +973,7 @@ Computes the next representable value after a given number towards a specified d **Usage:** ```tomo -nextafter(x: Num, y: Num) -> Num +nextafter(x: Num, y: Num -> Num) ``` **Parameters:** @@ -999,7 +999,7 @@ Generates a random floating-point number. **Usage:** ```tomo -random() -> Num +random(->Num) ``` **Parameters:** @@ -1023,7 +1023,7 @@ Rounds a number to the nearest integer, with ties rounded to the nearest even in **Usage:** ```tomo -rint(x: Num) -> Num +rint(x: Num -> Num) ``` **Parameters:** @@ -1050,7 +1050,7 @@ Rounds a number to the nearest whole number integer. **Usage:** ```tomo -round(x: Num) -> Num +round(x: Num -> Num) ``` **Parameters:** @@ -1077,7 +1077,7 @@ Formats a number in scientific notation with a specified precision. **Usage:** ```tomo -scientific(n: Num, precision: Int = 0) -> Text +scientific(n: Num, precision: Int = 0 -> Text) ``` **Parameters:** @@ -1103,7 +1103,7 @@ Extracts the significand (or mantissa) of a number. **Usage:** ```tomo -significand(x: Num) -> Num +significand(x: Num -> Num) ``` **Parameters:** @@ -1128,7 +1128,7 @@ Computes the sine of a number (angle in radians). **Usage:** ```tomo -sin(x: Num) -> Num +sin(x: Num -> Num) ``` **Parameters:** @@ -1153,7 +1153,7 @@ Computes the hyperbolic sine of a number. **Usage:** ```tomo -sinh(x: Num) -> Num +sinh(x: Num -> Num) ``` **Parameters:** @@ -1178,7 +1178,7 @@ Computes the square root of a number. **Usage:** ```tomo -sqrt(x: Num) -> Num +sqrt(x: Num -> Num) ``` **Parameters:** @@ -1203,7 +1203,7 @@ Computes the tangent of a number (angle in radians). **Usage:** ```tomo -tan(x: Num) -> Num +tan(x: Num -> Num) ``` **Parameters:** @@ -1228,7 +1228,7 @@ Computes the hyperbolic tangent of a number. **Usage:** ```tomo -tanh(x: Num) -> Num +tanh(x: Num -> Num) ``` **Parameters:** @@ -1253,7 +1253,7 @@ Computes the gamma function of a number. **Usage:** ```tomo -tgamma(x: Num) -> Num +tgamma(x: Num -> Num) ``` **Parameters:** @@ -1278,7 +1278,7 @@ Truncates a number to the nearest integer towards zero. **Usage:** ```tomo -trunc(x: Num) -> Num +trunc(x: Num -> Num) ``` **Parameters:** @@ -1305,7 +1305,7 @@ Computes the Bessel function of the second kind of order 0. **Usage:** ```tomo -y0(x: Num) -> Num +y0(x: Num -> Num) ``` **Parameters:** @@ -1330,7 +1330,7 @@ Computes the Bessel function of the second kind of order 1. **Usage:** ```tomo -y1(x: Num) -> Num +y1(x: Num -> Num) ``` **Parameters:** @@ -1356,7 +1356,7 @@ that range. **Usage:** ```tomo -clamped(x, low, high: Num) -> Num +clamped(x, low, high: Num -> Num) ``` **Parameters:** diff --git a/docs/paths.md b/docs/paths.md index b1f03ff..530560a 100644 --- a/docs/paths.md +++ b/docs/paths.md @@ -45,7 +45,7 @@ it doesn't already exist. Failure to write will result in a runtime error. **Usage:** ```markdown -append(path: Path, text: Text, permissions: Int32 = 0o644[32]) -> Void +append(path: Path, text: Text, permissions: Int32 = 0o644[32] -> Void) ``` **Parameters:** @@ -72,7 +72,7 @@ it doesn't already exist. Failure to write will result in a runtime error. **Usage:** ```markdown -append_bytes(path: Path, bytes: [Byte], permissions: Int32 = 0o644[32]) -> Void +append_bytes(path: Path, bytes: [Byte], permissions: Int32 = 0o644[32] -> Void) ``` **Parameters:** @@ -98,7 +98,7 @@ Returns the base name of the file or directory at the specified path. **Usage:** ```markdown -base_name(path: Path) -> Text +base_name(path: Path -> Text) ``` **Parameters:** @@ -124,7 +124,7 @@ or returns a null value if the file could not be opened. **Usage:** ```markdown -by_line(path: Path) -> (func()->Text?)? +by_line(path: Path -> (func()->Text?)?) ``` **Parameters:** @@ -158,7 +158,7 @@ Returns a list of children (files and directories) within the directory at the s **Usage:** ```markdown -children(path: Path, include_hidden=no) -> [Path] +children(path: Path, include_hidden=no -> [Path]) ``` **Parameters:** @@ -185,7 +185,7 @@ any of the parent directories do not exist, they will be created as needed. **Usage:** ```markdown -create_directory(path: Path, permissions=0o755[32]) -> Void +create_directory(path: Path, permissions=0o755[32] -> Void) ``` **Parameters:** @@ -210,7 +210,7 @@ Checks if a file or directory exists at the specified path. **Usage:** ```markdown -exists(path: Path) -> Bool +exists(path: Path -> Bool) ``` **Parameters:** @@ -235,7 +235,7 @@ Returns the file extension of the file at the specified path. Optionally returns **Usage:** ```markdown -extension(path: Path, full=yes) -> Text +extension(path: Path, full=yes -> Text) ``` **Parameters:** @@ -269,7 +269,7 @@ Returns a list of files within the directory at the specified path. Optionally i **Usage:** ```markdown -files(path: Path, include_hidden=no) -> [Path] +files(path: Path, include_hidden=no -> [Path]) ``` **Parameters:** @@ -295,7 +295,7 @@ Checks if the path represents a directory. Optionally follows symbolic links. **Usage:** ```markdown -is_directory(path: Path, follow_symlinks=yes) -> Bool +is_directory(path: Path, follow_symlinks=yes -> Bool) ``` **Parameters:** @@ -324,7 +324,7 @@ Checks if the path represents a file. Optionally follows symbolic links. **Usage:** ```markdown -is_file(path: Path, follow_symlinks=yes) -> Bool +is_file(path: Path, follow_symlinks=yes -> Bool) ``` **Parameters:** @@ -353,7 +353,7 @@ Checks if the path represents a socket. Optionally follows symbolic links. **Usage:** ```markdown -is_socket(path: Path, follow_symlinks=yes) -> Bool +is_socket(path: Path, follow_symlinks=yes -> Bool) ``` **Parameters:** @@ -379,7 +379,7 @@ Checks if the path represents a symbolic link. **Usage:** ```markdown -is_symlink(path: Path) -> Bool +is_symlink(path: Path -> Bool) ``` **Parameters:** @@ -404,7 +404,7 @@ Returns the parent directory of the file or directory at the specified path. **Usage:** ```markdown -parent(path: Path) -> Path +parent(path: Path -> Path) ``` **Parameters:** @@ -430,7 +430,7 @@ file could not be read. **Usage:** ```markdown -read(path: Path) -> Text? +read(path: Path -> Text?) ``` **Parameters:** @@ -460,7 +460,7 @@ file could not be read. **Usage:** ```markdown -read_bytes(path: Path) -> [Byte]? +read_bytes(path: Path -> [Byte]?) ``` **Parameters:** @@ -489,7 +489,7 @@ Returns the path relative to a given base path. By default, the base path is the **Usage:** ```markdown -relative(path: Path, relative_to=(./)) -> Path +relative(path: Path, relative_to=(./) -> Path) ``` **Parameters:** @@ -515,7 +515,7 @@ Removes the file or directory at the specified path. A runtime error is raised i **Usage:** ```markdown -remove(path: Path, ignore_missing=no) -> Void +remove(path: Path, ignore_missing=no -> Void) ``` **Parameters:** @@ -540,7 +540,7 @@ Resolves the absolute path of the given path relative to a base path. By default **Usage:** ```markdown -resolved(path: Path, relative_to=(./)) -> Path +resolved(path: Path, relative_to=(./) -> Path) ``` **Parameters:** @@ -569,7 +569,7 @@ Returns a list of subdirectories within the directory at the specified path. Opt **Usage:** ```markdown -subdirectories(path: Path, include_hidden=no) -> [Path] +subdirectories(path: Path, include_hidden=no -> [Path]) ``` **Parameters:** @@ -598,7 +598,7 @@ Generates a unique directory path based on the given path. Useful for creating t **Usage:** ```markdown -unique_directory(path: Path) -> Path +unique_directory(path: Path -> Path) ``` **Parameters:** @@ -629,7 +629,7 @@ writing cannot be successfully completed, a runtime error is raised. **Usage:** ```markdown -write(path: Path, text: Text, permissions=0o644[32]) -> Void +write(path: Path, text: Text, permissions=0o644[32] -> Void) ``` **Parameters:** @@ -657,7 +657,7 @@ writing cannot be successfully completed, a runtime error is raised. **Usage:** ```markdown -write(path: Path, bytes: [Byte], permissions=0o644[32]) -> Void +write(path: Path, bytes: [Byte], permissions=0o644[32] -> Void) ``` **Parameters:** @@ -685,7 +685,7 @@ files. **Usage:** ```markdown -write_unique(path: Path, text: Text) -> Path +write_unique(path: Path, text: Text -> Path) ``` **Parameters:** @@ -717,7 +717,7 @@ files. **Usage:** ```markdown -write_unique_bytes(path: Path, bytes: [Byte]) -> Path +write_unique_bytes(path: Path, bytes: [Byte] -> Path) ``` **Parameters:** diff --git a/docs/ranges.md b/docs/ranges.md index 4771bd5..6565f94 100644 --- a/docs/ranges.md +++ b/docs/ranges.md @@ -20,7 +20,7 @@ Returns a reversed copy of the range. **Usage:** ```tomo -reversed(range: Range) -> Range +reversed(range: Range -> Range) ``` **Parameters:** @@ -45,7 +45,7 @@ Creates a new range with a specified step value. **Usage:** ```tomo -by(range: Range, step: Int) -> Range +by(range: Range, step: Int -> Range) ``` **Parameters:** diff --git a/docs/sets.md b/docs/sets.md index 850d144..a0a1778 100644 --- a/docs/sets.md +++ b/docs/sets.md @@ -82,7 +82,7 @@ Checks if the set contains a specified item. **Usage:** ```tomo -has(set:{T}, item:T) -> Bool +has(set:{T}, item:T -> Bool) ``` **Parameters:** @@ -108,7 +108,7 @@ Adds an item to the set. **Usage:** ```tomo -add(set:{T}, item: T) -> Void +add(set:{T}, item: T -> Void) ``` **Parameters:** @@ -133,7 +133,7 @@ Adds multiple items to the set. **Usage:** ```tomo -add_all(set:&{T}, items: [T]) -> Void +add_all(set:&{T}, items: [T] -> Void) ``` **Parameters:** @@ -158,7 +158,7 @@ Removes an item from the set. **Usage:** ```tomo -remove(set:&{T}, item: T) -> Void +remove(set:&{T}, item: T -> Void) ``` **Parameters:** @@ -183,7 +183,7 @@ Removes multiple items from the set. **Usage:** ```tomo -remove_all(set:&{T}, items: [T]) -> Void +remove_all(set:&{T}, items: [T] -> Void) ``` **Parameters:** @@ -208,7 +208,7 @@ Removes all items from the set. **Usage:** ```tomo -clear(set:&{T}) -> Void +clear(set:&{T} -> Void) ``` **Parameters:** @@ -232,7 +232,7 @@ Creates a new set that is the union of the original set and another set. **Usage:** ```tomo -with(set:{T}, other: {T}) -> {T} +with(set:{T}, other: {T} -> {T}) ``` **Parameters:** @@ -258,7 +258,7 @@ Creates a new set with items that are in both the original set and another set. **Usage:** ```tomo -overlap(set:{T}, other: {T}) -> {T} +overlap(set:{T}, other: {T} -> {T}) ``` **Parameters:** @@ -284,7 +284,7 @@ Creates a new set with items from the original set but without items from anothe **Usage:** ```tomo -without(set:{T}, other: {T}) -> {T} +without(set:{T}, other: {T} -> {T}) ``` **Parameters:** @@ -310,7 +310,7 @@ Checks if the set is a subset of another set. **Usage:** ```tomo -set:is_subset_of(other: {T}, strict: Bool = no) -> Bool +set:is_subset_of(other: {T}, strict: Bool = no -> Bool) ``` **Parameters:** @@ -337,7 +337,7 @@ Checks if the set is a superset of another set. **Usage:** ```tomo -is_superset_of(set:{T}, other: {T}, strict: Bool = no) -> Bool +is_superset_of(set:{T}, other: {T}, strict: Bool = no -> Bool) ``` **Parameters:** diff --git a/docs/tables.md b/docs/tables.md index f589eb2..e0c9ff3 100644 --- a/docs/tables.md +++ b/docs/tables.md @@ -118,7 +118,7 @@ not already in the table, its value will be assumed to be zero. **Usage:** ```markdown -bump(t:{K:V}, key: K, amount: Int = 1) -> Void +bump(t:{K:V}, key: K, amount: Int = 1 -> Void) ``` **Parameters:** @@ -148,7 +148,7 @@ Removes all key-value pairs from the table. **Usage:** ```markdown -t:clear() -> Void +t:clear() ``` **Parameters:** @@ -172,7 +172,7 @@ Retrieves the value associated with a key, or returns null if the key is not pre **Usage:** ```markdown -t:get(key: K) -> V? +t:get(key: K -> V?) ``` **Parameters:** @@ -208,7 +208,7 @@ Checks if the table contains a specified key. **Usage:** ```markdown -has(t:{K:V}, key: K) -> Bool +has(t:{K:V}, key: K -> Bool) ``` **Parameters:** @@ -236,7 +236,7 @@ Removes the key-value pair associated with a specified key. **Usage:** ```markdown -remove(t:{K:V}, key: K) -> Void +remove(t:{K:V}, key: K -> Void) ``` **Parameters:** @@ -264,7 +264,7 @@ Sets or updates the value associated with a specified key. **Usage:** ```markdown -set(t:{K:V}, key: K, value: V) -> Void +set(t:{K:V}, key: K, value: V -> Void) ``` **Parameters:** diff --git a/docs/text.md b/docs/text.md index 3836953..aca5c04 100644 --- a/docs/text.md +++ b/docs/text.md @@ -402,7 +402,7 @@ Converts a `Text` value to a C-style string. **Usage:** ```tomo -as_c_string(text: Text) -> CString +as_c_string(text: Text -> CString) ``` **Parameters:** @@ -428,7 +428,7 @@ the text. **Usage:** ```tomo -utf8_bytes(text: Text) -> [Byte] +utf8_bytes(text: Text -> [Byte]) ``` **Parameters:** @@ -453,7 +453,7 @@ Returns an array of the names of each codepoint in the text. **Usage:** ```tomo -codepoint_names(text: Text) -> [Text] +codepoint_names(text: Text -> [Text]) ``` **Parameters:** @@ -478,7 +478,7 @@ Returns an array of Unicode code points for UTF32 encoding of the text. **Usage:** ```tomo -utf32_codepoints(text: Text) -> [Int32] +utf32_codepoints(text: Text -> [Int32]) ``` **Parameters:** @@ -503,7 +503,7 @@ Checks if the `Text` ends with a literal suffix text. **Usage:** ```tomo -ends_with(text: Text, suffix: Text) -> Bool +ends_with(text: Text, suffix: Text -> Bool) ``` **Parameters:** @@ -529,7 +529,7 @@ Converts a C-style string to a `Text` value. **Usage:** ```tomo -from_c_string(str: CString) -> Text +from_c_string(str: CString -> Text) ``` **Parameters:** @@ -556,7 +556,7 @@ resulting text's codepoints may not exactly match the input codepoints. **Usage:** ```tomo -from_codepoint_names(codepoint_names: [Text]) -> [Text] +from_codepoint_names(codepoint_names: [Text] -> [Text]) ``` **Parameters:** @@ -589,7 +589,7 @@ match the input codepoints. **Usage:** ```tomo -from_codepoint_names(codepoints: [Int32]) -> [Text] +from_codepoint_names(codepoints: [Int32] -> [Text]) ``` **Parameters:** @@ -616,7 +616,7 @@ match the input. **Usage:** ```tomo -from_codepoint_names(codepoints: [Int32]) -> [Text] +from_codepoint_names(codepoints: [Int32] -> [Text]) ``` **Parameters:** @@ -642,7 +642,7 @@ See: [Patterns](#Patterns) for more information on patterns. **Usage:** ```tomo -find(text: Text, pattern: Pattern, start: Int = 1, length: &Int64? = !&Int64) -> Int +find(text: Text, pattern: Pattern, start: Int = 1, length: &Int64? = !&Int64 -> Int) ``` **Parameters:** @@ -685,7 +685,7 @@ See: [Patterns](#Patterns) for more information on patterns. **Usage:** ```tomo -find_all(text: Text, pattern: Pattern) -> [Text] +find_all(text: Text, pattern: Pattern -> [Text]) ``` **Parameters:** @@ -727,7 +727,7 @@ Checks if the `Text` contains a target pattern (see: [Patterns](#Patterns)). **Usage:** ```tomo -has(text: Text, pattern: Pattern) -> Bool +has(text: Text, pattern: Pattern -> Bool) ``` **Parameters:** @@ -759,7 +759,7 @@ Joins an array of text pieces with a specified glue. **Usage:** ```tomo -join(glue: Text, pieces: [Text]) -> Text +join(glue: Text, pieces: [Text] -> Text) ``` **Parameters:** @@ -786,7 +786,7 @@ ignoring trailing newlines, and handling `\r\n` the same as `\n`. **Usage:** ```tomo -split(text: Text) -> [Text] +split(text: Text -> [Text]) ``` **Parameters:** @@ -819,7 +819,7 @@ Converts all characters in the text to lowercase. **Usage:** ```tomo -lower(text: Text) -> Text +lower(text: Text -> Text) ``` **Parameters:** @@ -846,7 +846,7 @@ doesn't match the pattern. **Usage:** ```tomo -matches(text: Text, pattern: Pattern) -> [Text] +matches(text: Text, pattern: Pattern -> [Text]) ``` **Parameters:** @@ -877,7 +877,7 @@ calling the given function on that text. **Usage:** ```tomo -map(text: Text, pattern: Pattern, fn: func(text:Text)->Text) -> Text +map(text: Text, pattern: Pattern, fn: func(text:Text)->Text -> Text) ``` **Parameters:** @@ -907,7 +907,7 @@ Formats the text as a quoted string. **Usage:** ```tomo -quoted(text: Text, color: Bool = no) -> Text +quoted(text: Text, color: Bool = no -> Text) ``` **Parameters:** @@ -933,7 +933,7 @@ Repeat some text multiple times. **Usage:** ```tomo -repeat(text: Text, count:Int) -> Text +repeat(text: Text, count:Int -> Text) ``` **Parameters:** @@ -961,7 +961,7 @@ See [Patterns](#patterns) for more information about patterns. **Usage:** ```tomo -replace(text: Text, pattern: Pattern, replacement: Text, backref: Pattern = $/\/, recursive: Bool = yes) -> Text +replace(text: Text, pattern: Pattern, replacement: Text, backref: Pattern = $/\/, recursive: Bool = yes -> Text) ``` **Parameters:** @@ -1030,7 +1030,7 @@ See [`replace()`](#replace) for more information about replacement behavior. **Usage:** ```tomo -replace_all(replacements:{Pattern:Text}, backref: Pattern = $/\/) -> Text +replace_all(replacements:{Pattern:Text}, backref: Pattern = $/\/ -> Text) ``` **Parameters:** @@ -1075,7 +1075,7 @@ See [Patterns](#patterns) for more information about patterns. **Usage:** ```tomo -split(text: Text, pattern: Pattern = "") -> [Text] +split(text: Text, pattern: Pattern = "" -> [Text]) ``` **Parameters:** @@ -1111,7 +1111,7 @@ Checks if the `Text` starts with a literal prefix text. **Usage:** ```tomo -starts_with(text: Text, prefix: Text) -> Bool +starts_with(text: Text, prefix: Text -> Bool) ``` **Parameters:** @@ -1137,7 +1137,7 @@ Converts the text to title case (capitalizing the first letter of each word). **Usage:** ```tomo -title(text: Text) -> Text +title(text: Text -> Text) ``` **Parameters:** @@ -1163,7 +1163,7 @@ See [Patterns](#patterns) for more information about patterns. **Usage:** ```tomo -trim(text: Text, pattern: Pattern = $/{whitespace/, trim_left: Bool = yes, trim_right: Bool = yes) -> Text +trim(text: Text, pattern: Pattern = $/{whitespace/, trim_left: Bool = yes, trim_right: Bool = yes -> Text) ``` **Parameters:** @@ -1197,7 +1197,7 @@ Converts all characters in the text to uppercase. **Usage:** ```tomo -upper(text: Text) -> Text +upper(text: Text -> Text) ``` **Parameters:** diff --git a/docs/threads.md b/docs/threads.md index 228fc8a..1580df8 100644 --- a/docs/threads.md +++ b/docs/threads.md @@ -13,7 +13,7 @@ Creates a new thread to execute a specified function. **Usage:** ```tomo -Thread.new(fn: func() -> Void) -> Thread +Thread.new(fn: func(->Void) -> Thread) ``` **Parameters:** @@ -47,7 +47,7 @@ Requests the cancellation of a specified thread. **Usage:** ```tomo -cancel(thread: Thread) -> Void +cancel(thread: Thread) ``` **Parameters:** @@ -71,7 +71,7 @@ Waits for a specified thread to terminate. **Usage:** ```tomo -join(thread: Thread) -> Void +join(thread: Thread) ``` **Parameters:** @@ -95,7 +95,7 @@ Detaches a specified thread, allowing it to run independently. **Usage:** ```tomo -detach(thread: Thread) -> Void +detach(thread: Thread) ``` **Parameters:** diff --git a/environment.c b/environment.c index f6e4557..96bc51f 100644 --- a/environment.c +++ b/environment.c @@ -88,130 +88,130 @@ env_t *new_compilation_unit(CORD libname) {"Void", Type(VoidType), "Void_t", "Void$info", {}}, {"Memory", Type(MemoryType), "Memory_t", "Memory$info", {}}, {"Bool", Type(BoolType), "Bool_t", "Bool$info", TypedArray(ns_entry_t, - {"from_text", "Bool$from_text", "func(text:Text)->Bool?"}, - {"random", "Bool$random", "func(p=0.5)->Bool"}, + {"from_text", "Bool$from_text", "func(text:Text -> Bool?)"}, + {"random", "Bool$random", "func(p=0.5 -> Bool)"}, )}, {"Byte", Type(ByteType), "Byte_t", "Byte$info", TypedArray(ns_entry_t, {"max", "Byte$max", "Byte"}, {"min", "Byte$min", "Byte"}, - {"random", "Byte$random", "func(min=Byte.min, max=Byte.max)->Byte"}, + {"random", "Byte$random", "func(min=Byte.min, max=Byte.max -> Byte)"}, )}, {"Int", Type(BigIntType), "Int_t", "Int$info", TypedArray(ns_entry_t, - {"abs", "Int$abs", "func(x:Int)->Int"}, - {"bit_and", "Int$bit_and", "func(x,y:Int)->Int"}, - {"bit_or", "Int$bit_or", "func(x,y:Int)->Int"}, - {"bit_xor", "Int$bit_xor", "func(x,y:Int)->Int"}, - {"clamped", "Int$clamped", "func(x,low,high:Int)->Int"}, - {"divided_by", "Int$divided_by", "func(x,y:Int)->Int"}, - {"format", "Int$format", "func(i:Int, digits=0)->Text"}, - {"from_text", "Int$from_text", "func(text:Text)->Int?"}, - {"hex", "Int$hex", "func(i:Int, digits=0, uppercase=yes, prefix=yes)->Text"}, - {"is_prime", "Int$is_prime", "func(x:Int,reps=50)->Bool"}, - {"left_shifted", "Int$left_shifted", "func(x,y:Int)->Int"}, - {"minus", "Int$minus", "func(x,y:Int)->Int"}, - {"modulo", "Int$modulo", "func(x,y:Int)->Int"}, - {"modulo1", "Int$modulo1", "func(x,y:Int)->Int"}, - {"negated", "Int$negated", "func(x:Int)->Int"}, - {"negative", "Int$negative", "func(x:Int)->Int"}, - {"next_prime", "Int$next_prime", "func(x:Int)->Int"}, - {"octal", "Int$octal", "func(i:Int, digits=0, prefix=yes)->Text"}, - {"plus", "Int$plus", "func(x,y:Int)->Int"}, - {"power", "Int$power", "func(base:Int,exponent:Int)->Int"}, - {"prev_prime", "Int$prev_prime", "func(x:Int)->Int"}, - {"random", "Int$random", "func(min,max:Int)->Int"}, - {"right_shifted", "Int$right_shifted", "func(x,y:Int)->Int"}, - {"sqrt", "Int$sqrt", "func(x:Int)->Int"}, - {"times", "Int$times", "func(x,y:Int)->Int"}, - {"to", "Int$to", "func(from:Int,to:Int)->Range"}, + {"abs", "Int$abs", "func(x:Int -> Int)"}, + {"bit_and", "Int$bit_and", "func(x,y:Int -> Int)"}, + {"bit_or", "Int$bit_or", "func(x,y:Int -> Int)"}, + {"bit_xor", "Int$bit_xor", "func(x,y:Int -> Int)"}, + {"clamped", "Int$clamped", "func(x,low,high:Int -> Int)"}, + {"divided_by", "Int$divided_by", "func(x,y:Int -> Int)"}, + {"format", "Int$format", "func(i:Int, digits=0 -> Text)"}, + {"from_text", "Int$from_text", "func(text:Text -> Int?)"}, + {"hex", "Int$hex", "func(i:Int, digits=0, uppercase=yes, prefix=yes -> Text)"}, + {"is_prime", "Int$is_prime", "func(x:Int,reps=50 -> Bool)"}, + {"left_shifted", "Int$left_shifted", "func(x,y:Int -> Int)"}, + {"minus", "Int$minus", "func(x,y:Int -> Int)"}, + {"modulo", "Int$modulo", "func(x,y:Int -> Int)"}, + {"modulo1", "Int$modulo1", "func(x,y:Int -> Int)"}, + {"negated", "Int$negated", "func(x:Int -> Int)"}, + {"negative", "Int$negative", "func(x:Int -> Int)"}, + {"next_prime", "Int$next_prime", "func(x:Int -> Int)"}, + {"octal", "Int$octal", "func(i:Int, digits=0, prefix=yes -> Text)"}, + {"plus", "Int$plus", "func(x,y:Int -> Int)"}, + {"power", "Int$power", "func(base:Int,exponent:Int -> Int)"}, + {"prev_prime", "Int$prev_prime", "func(x:Int -> Int)"}, + {"random", "Int$random", "func(min,max:Int -> Int)"}, + {"right_shifted", "Int$right_shifted", "func(x,y:Int -> Int)"}, + {"sqrt", "Int$sqrt", "func(x:Int -> Int)"}, + {"times", "Int$times", "func(x,y:Int -> Int)"}, + {"to", "Int$to", "func(from:Int,to:Int -> Range)"}, )}, {"Int64", Type(IntType, .bits=TYPE_IBITS64), "Int64_t", "Int64$info", TypedArray(ns_entry_t, - {"abs", "labs", "func(i:Int64)->Int64"}, - {"bits", "Int64$bits", "func(x:Int64)->[Bool]"}, - {"clamped", "Int64$clamped", "func(x,low,high:Int64)->Int64"}, - {"divided_by", "Int64$divided_by", "func(x,y:Int64)->Int64"}, - {"format", "Int64$format", "func(i:Int64, digits=0)->Text"}, - {"from_text", "Int64$from_text", "func(text:Text)->Int64?"}, - {"hex", "Int64$hex", "func(i:Int64, digits=0, uppercase=yes, prefix=yes)->Text"}, + {"abs", "labs", "func(i:Int64 -> Int64)"}, + {"bits", "Int64$bits", "func(x:Int64 -> [Bool])"}, + {"clamped", "Int64$clamped", "func(x,low,high:Int64 -> Int64)"}, + {"divided_by", "Int64$divided_by", "func(x,y:Int64 -> Int64)"}, + {"format", "Int64$format", "func(i:Int64, digits=0 -> Text)"}, + {"from_text", "Int64$from_text", "func(text:Text -> Int64?)"}, + {"hex", "Int64$hex", "func(i:Int64, digits=0, uppercase=yes, prefix=yes -> Text)"}, {"max", "Int64$max", "Int64"}, {"min", "Int64$min", "Int64"}, - {"modulo", "Int64$modulo", "func(x,y:Int64)->Int64"}, - {"modulo1", "Int64$modulo1", "func(x,y:Int64)->Int64"}, - {"octal", "Int64$octal", "func(i:Int64, digits=0, prefix=yes)->Text"}, - {"to", "Int64$to", "func(from:Int64,to:Int64)->Range"}, + {"modulo", "Int64$modulo", "func(x,y:Int64 -> Int64)"}, + {"modulo1", "Int64$modulo1", "func(x,y:Int64 -> Int64)"}, + {"octal", "Int64$octal", "func(i:Int64, digits=0, prefix=yes -> Text)"}, + {"to", "Int64$to", "func(from:Int64,to:Int64 -> Range)"}, // Must be defined after min/max: - {"random", "Int64$random", "func(min=Int64.min, max=Int64.max)->Int64"}, + {"random", "Int64$random", "func(min=Int64.min, max=Int64.max -> Int64)"}, )}, {"Int32", Type(IntType, .bits=TYPE_IBITS32), "Int32_t", "Int32$info", TypedArray(ns_entry_t, - {"abs", "abs", "func(i:Int32)->Int32"}, - {"bits", "Int32$bits", "func(x:Int32)->[Bool]"}, - {"clamped", "Int32$clamped", "func(x,low,high:Int32)->Int32"}, - {"divided_by", "Int32$divided_by", "func(x,y:Int32)->Int32"}, - {"format", "Int32$format", "func(i:Int32, digits=0)->Text"}, - {"from_text", "Int32$from_text", "func(text:Text)->Int32?"}, - {"hex", "Int32$hex", "func(i:Int32, digits=0, uppercase=yes, prefix=yes)->Text"}, + {"abs", "abs", "func(i:Int32 -> Int32)"}, + {"bits", "Int32$bits", "func(x:Int32 -> [Bool])"}, + {"clamped", "Int32$clamped", "func(x,low,high:Int32 -> Int32)"}, + {"divided_by", "Int32$divided_by", "func(x,y:Int32 -> Int32)"}, + {"format", "Int32$format", "func(i:Int32, digits=0 -> Text)"}, + {"from_text", "Int32$from_text", "func(text:Text -> Int32?)"}, + {"hex", "Int32$hex", "func(i:Int32, digits=0, uppercase=yes, prefix=yes -> Text)"}, {"max", "Int32$max", "Int32"}, {"min", "Int32$min", "Int32"}, - {"modulo", "Int32$modulo", "func(x,y:Int32)->Int32"}, - {"modulo1", "Int32$modulo1", "func(x,y:Int32)->Int32"}, - {"octal", "Int32$octal", "func(i:Int32, digits=0, prefix=yes)->Text"}, - {"to", "Int32$to", "func(from:Int32,to:Int32)->Range"}, + {"modulo", "Int32$modulo", "func(x,y:Int32 -> Int32)"}, + {"modulo1", "Int32$modulo1", "func(x,y:Int32 -> Int32)"}, + {"octal", "Int32$octal", "func(i:Int32, digits=0, prefix=yes -> Text)"}, + {"to", "Int32$to", "func(from:Int32,to:Int32 -> Range)"}, // Must be defined after min/max: - {"random", "Int32$random", "func(min=Int32.min, max=Int32.max)->Int32"}, + {"random", "Int32$random", "func(min=Int32.min, max=Int32.max -> Int32)"}, )}, {"Int16", Type(IntType, .bits=TYPE_IBITS16), "Int16_t", "Int16$info", TypedArray(ns_entry_t, - {"abs", "abs", "func(i:Int16)->Int16"}, - {"bits", "Int16$bits", "func(x:Int16)->[Bool]"}, - {"clamped", "Int16$clamped", "func(x,low,high:Int16)->Int16"}, - {"divided_by", "Int16$divided_by", "func(x,y:Int16)->Int16"}, - {"format", "Int16$format", "func(i:Int16, digits=0)->Text"}, - {"from_text", "Int16$from_text", "func(text:Text)->Int16?"}, - {"hex", "Int16$hex", "func(i:Int16, digits=0, uppercase=yes, prefix=yes)->Text"}, + {"abs", "abs", "func(i:Int16 -> Int16)"}, + {"bits", "Int16$bits", "func(x:Int16 -> [Bool])"}, + {"clamped", "Int16$clamped", "func(x,low,high:Int16 -> Int16)"}, + {"divided_by", "Int16$divided_by", "func(x,y:Int16 -> Int16)"}, + {"format", "Int16$format", "func(i:Int16, digits=0 -> Text)"}, + {"from_text", "Int16$from_text", "func(text:Text -> Int16?)"}, + {"hex", "Int16$hex", "func(i:Int16, digits=0, uppercase=yes, prefix=yes -> Text)"}, {"max", "Int16$max", "Int16"}, {"min", "Int16$min", "Int16"}, - {"modulo", "Int16$modulo", "func(x,y:Int16)->Int16"}, - {"modulo1", "Int16$modulo1", "func(x,y:Int16)->Int16"}, - {"octal", "Int16$octal", "func(i:Int16, digits=0, prefix=yes)->Text"}, - {"to", "Int16$to", "func(from:Int16,to:Int16)->Range"}, + {"modulo", "Int16$modulo", "func(x,y:Int16 -> Int16)"}, + {"modulo1", "Int16$modulo1", "func(x,y:Int16 -> Int16)"}, + {"octal", "Int16$octal", "func(i:Int16, digits=0, prefix=yes -> Text)"}, + {"to", "Int16$to", "func(from:Int16,to:Int16 -> Range)"}, // Must be defined after min/max: - {"random", "Int16$random", "func(min=Int16.min, max=Int16.max)->Int16"}, + {"random", "Int16$random", "func(min=Int16.min, max=Int16.max -> Int16)"}, )}, {"Int8", Type(IntType, .bits=TYPE_IBITS8), "Int8_t", "Int8$info", TypedArray(ns_entry_t, - {"abs", "abs", "func(i:Int8)->Int8"}, - {"bits", "Int8$bits", "func(x:Int8)->[Bool]"}, - {"clamped", "Int8$clamped", "func(x,low,high:Int8)->Int8"}, - {"divided_by", "Int8$divided_by", "func(x,y:Int8)->Int8"}, - {"format", "Int8$format", "func(i:Int8, digits=0)->Text"}, - {"from_text", "Int8$from_text", "func(text:Text)->Int8?"}, - {"hex", "Int8$hex", "func(i:Int8, digits=0, uppercase=yes, prefix=yes)->Text"}, + {"abs", "abs", "func(i:Int8 -> Int8)"}, + {"bits", "Int8$bits", "func(x:Int8 -> [Bool])"}, + {"clamped", "Int8$clamped", "func(x,low,high:Int8 -> Int8)"}, + {"divided_by", "Int8$divided_by", "func(x,y:Int8 -> Int8)"}, + {"format", "Int8$format", "func(i:Int8, digits=0 -> Text)"}, + {"from_text", "Int8$from_text", "func(text:Text -> Int8?)"}, + {"hex", "Int8$hex", "func(i:Int8, digits=0, uppercase=yes, prefix=yes -> Text)"}, {"max", "Int8$max", "Int8"}, {"min", "Int8$min", "Int8"}, - {"modulo", "Int8$modulo", "func(x,y:Int8)->Int8"}, - {"modulo1", "Int8$modulo1", "func(x,y:Int8)->Int8"}, - {"octal", "Int8$octal", "func(i:Int8, digits=0, prefix=yes)->Text"}, - {"to", "Int8$to", "func(from:Int8,to:Int8)->Range"}, + {"modulo", "Int8$modulo", "func(x,y:Int8 -> Int8)"}, + {"modulo1", "Int8$modulo1", "func(x,y:Int8 -> Int8)"}, + {"octal", "Int8$octal", "func(i:Int8, digits=0, prefix=yes -> Text)"}, + {"to", "Int8$to", "func(from:Int8,to:Int8 -> Range)"}, // Must be defined after min/max: - {"random", "Int8$random", "func(min=Int8.min, max=Int8.max)->Int8"}, + {"random", "Int8$random", "func(min=Int8.min, max=Int8.max -> Int8)"}, )}, #define C(name) {#name, "M_"#name, "Num"} -#define F(name) {#name, #name, "func(n:Num)->Num"} -#define F2(name) {#name, #name, "func(x,y:Num)->Num"} +#define F(name) {#name, #name, "func(n:Num -> Num)"} +#define F2(name) {#name, #name, "func(x,y:Num -> Num)"} {"Num", Type(NumType, .bits=TYPE_NBITS64), "Num_t", "Num$info", TypedArray(ns_entry_t, - {"near", "Num$near", "func(x,y:Num, ratio=1e-9, min_epsilon=1e-9)->Bool"}, - {"clamped", "Num$clamped", "func(x,low,high:Num)->Num"}, - {"format", "Num$format", "func(n:Num, precision=0)->Text"}, - {"scientific", "Num$scientific", "func(n:Num, precision=0)->Text"}, - {"nan", "Num$nan", "func(tag=\"\")->Num"}, - {"isinf", "Num$isinf", "func(n:Num)->Bool"}, - {"isfinite", "Num$isfinite", "func(n:Num)->Bool"}, - {"isnan", "Num$isnan", "func(n:Num)->Bool"}, + {"near", "Num$near", "func(x,y:Num, ratio=1e-9, min_epsilon=1e-9 -> Bool)"}, + {"clamped", "Num$clamped", "func(x,low,high:Num -> Num)"}, + {"format", "Num$format", "func(n:Num, precision=0 -> Text)"}, + {"scientific", "Num$scientific", "func(n:Num,precision=0 -> Text)"}, + {"nan", "Num$nan", "func(tag=\"\" -> Num)"}, + {"isinf", "Num$isinf", "func(n:Num -> Bool)"}, + {"isfinite", "Num$isfinite", "func(n:Num -> Bool)"}, + {"isnan", "Num$isnan", "func(n:Num -> Bool)"}, C(2_SQRTPI), C(E), C(PI_2), C(2_PI), C(1_PI), C(LN10), C(LN2), C(LOG2E), C(PI), C(PI_4), C(SQRT2), C(SQRT1_2), {"INF", "(Num_t)(INFINITY)", "Num"}, {"TAU", "(Num_t)(2.*M_PI)", "Num"}, - {"random", "Num$random", "func()->Num"}, - {"mix", "Num$mix", "func(amount,x,y:Num)->Num"}, - {"from_text", "Num$from_text", "func(text:Text)->Num?"}, - {"abs", "fabs", "func(n:Num)->Num"}, + {"random", "Num$random", "func(->Num)"}, + {"mix", "Num$mix", "func(amount,x,y:Num -> Num)"}, + {"from_text", "Num$from_text", "func(text:Text -> Num?)"}, + {"abs", "fabs", "func(n:Num -> Num)"}, F(acos), F(acosh), F(asin), F(asinh), F(atan), F(atanh), F(cbrt), F(ceil), F(cos), F(cosh), F(erf), F(erfc), F(exp), F(exp2), F(expm1), F(floor), F(j0), F(j1), F(log), F(log10), F(log1p), F(log2), F(logb), F(rint), F(round), F(significand), F(sin), F(sinh), F(sqrt), @@ -222,25 +222,25 @@ env_t *new_compilation_unit(CORD libname) #undef F #undef C #define C(name) {#name, "(Num32_t)(M_"#name")", "Num32"} -#define F(name) {#name, #name"f", "func(n:Num32)->Num32"} -#define F2(name) {#name, #name"f", "func(x,y:Num32)->Num32"} +#define F(name) {#name, #name"f", "func(n:Num32 -> Num32)"} +#define F2(name) {#name, #name"f", "func(x,y:Num32 -> Num32)"} {"Num32", Type(NumType, .bits=TYPE_NBITS32), "Num32_t", "Num32$info", TypedArray(ns_entry_t, - {"near", "Num32$near", "func(x,y:Num32, ratio=1e-9f32, min_epsilon=1e-9f32)->Bool"}, - {"clamped", "Num32$clamped", "func(x,low,high:Num32)->Num32"}, - {"format", "Num32$format", "func(n:Num32, precision=0)->Text"}, - {"scientific", "Num32$scientific", "func(n:Num32, precision=0)->Text"}, - {"nan", "Num32$nan", "func(tag=\"\")->Num32"}, - {"isinf", "Num32$isinf", "func(n:Num32)->Bool"}, - {"isfinite", "Num32$isfinite", "func(n:Num32)->Bool"}, - {"isnan", "Num32$isnan", "func(n:Num32)->Bool"}, + {"near", "Num32$near", "func(x,y:Num32, ratio=1e-9f32, min_epsilon=1e-9f32 -> Bool)"}, + {"clamped", "Num32$clamped", "func(x,low,high:Num32 -> Num32)"}, + {"format", "Num32$format", "func(n:Num32, precision=0 -> Text)"}, + {"scientific", "Num32$scientific", "func(n:Num32, precision=0 -> Text)"}, + {"nan", "Num32$nan", "func(tag=\"\" -> Num32)"}, + {"isinf", "Num32$isinf", "func(n:Num32 -> Bool)"}, + {"isfinite", "Num32$isfinite", "func(n:Num32 -> Bool)"}, + {"isnan", "Num32$isnan", "func(n:Num32 -> Bool)"}, C(2_SQRTPI), C(E), C(PI_2), C(2_PI), C(1_PI), C(LN10), C(LN2), C(LOG2E), C(PI), C(PI_4), C(SQRT2), C(SQRT1_2), {"INF", "(Num32_t)(INFINITY)", "Num32"}, {"TAU", "(Num32_t)(2.f*M_PI)", "Num32"}, - {"random", "Num32$random", "func()->Num32"}, - {"mix", "Num32$mix", "func(amount,x,y:Num32)->Num32"}, - {"from_text", "Num32$from_text", "func(text:Text)->Num32?"}, - {"abs", "fabsf", "func(n:Num32)->Num32"}, + {"random", "Num32$random", "func(->Num32)"}, + {"mix", "Num32$mix", "func(amount,x,y:Num32 -> Num32)"}, + {"from_text", "Num32$from_text", "func(text:Text -> Num32?)"}, + {"abs", "fabsf", "func(n:Num32 -> Num32)"}, F(acos), F(acosh), F(asin), F(asinh), F(atan), F(atanh), F(cbrt), F(ceil), F(cos), F(cosh), F(erf), F(erfc), F(exp), F(exp2), F(expm1), F(floor), F(j0), F(j1), F(log), F(log10), F(log1p), F(log2), F(logb), F(rint), F(round), F(significand), F(sin), F(sinh), F(sqrt), @@ -248,122 +248,122 @@ env_t *new_compilation_unit(CORD libname) F2(atan2), F2(copysign), F2(fdim), F2(hypot), F2(nextafter), F2(pow), F2(remainder), )}, {"CString", Type(CStringType), "char*", "CString$info", TypedArray(ns_entry_t, - {"as_text", "CString$as_text_simple", "func(str:CString)->Text"}, + {"as_text", "CString$as_text_simple", "func(str:CString -> Text)"}, )}, #undef F2 #undef F #undef C {"Range", RANGE_TYPE, "Range_t", "Range", TypedArray(ns_entry_t, - {"reversed", "Range$reversed", "func(range:Range)->Range"}, - {"by", "Range$by", "func(range:Range, step:Int)->Range"}, + {"reversed", "Range$reversed", "func(range:Range -> Range)"}, + {"by", "Range$by", "func(range:Range, step:Int -> Range)"}, )}, {"Pattern", Type(TextType, .lang="Pattern", .env=namespace_env(env, "Pattern")), "Pattern_t", "Pattern$info", TypedArray(ns_entry_t, - {"escape_int", "Int$value_as_text", "func(i:Int)->Pattern"}, - {"escape_text", "Pattern$escape_text", "func(text:Text)->Pattern"}, + {"escape_int", "Int$value_as_text", "func(i:Int -> Pattern)"}, + {"escape_text", "Pattern$escape_text", "func(text:Text -> Pattern)"}, )}, {"DateTime", Type(DateTimeType), "DateTime_t", "DateTime", TypedArray(ns_entry_t, // Used as a default for functions below: - {"now", "DateTime$now", "func()->DateTime"}, + {"now", "DateTime$now", "func(->DateTime)"}, - {"after", "DateTime$after", "func(dt:DateTime,seconds,minutes,hours=0.0,days,weeks,months,years=0,timezone=!Text)->DateTime"}, - {"date", "DateTime$date", "func(dt:DateTime,timezone=!Text)->Text"}, - {"format", "DateTime$format", "func(dt:DateTime,format=\"%Y-%m-%dT%H:%M:%S%z\",timezone=!Text)->Text"}, - {"from_unix_timestamp", "DateTime$from_unix_timestamp", "func(timestamp:Int64)->DateTime"}, - {"get", "DateTime$get", "func(dt:DateTime,year,month,day,hour,minute,second,nanosecond,weekday=!&Int, timezone=!Text)"}, - {"get_local_timezone", "DateTime$get_local_timezone", "func()->Text"}, - {"hours_till", "DateTime$hours_till", "func(now,then:DateTime)->Num"}, - {"minutes_till", "DateTime$minutes_till", "func(now,then:DateTime)->Num"}, - {"new", "DateTime$new", "func(year,month,day:Int,hour,minute=0,second=0.0,timezone=!Text)->DateTime"}, - {"parse", "DateTime$parse", "func(text:Text, format=\"%Y-%m-%dT%H:%M:%S%z\")->DateTime?"}, - {"relative", "DateTime$relative", "func(dt:DateTime,relative_to=DateTime.now(),timezone=!Text)->Text"}, - {"seconds_till", "DateTime$seconds_till", "func(now:DateTime,then:DateTime)->Num"}, + {"after", "DateTime$after", "func(dt:DateTime,seconds,minutes,hours=0.0,days,weeks,months,years=0,timezone=!Text -> DateTime)"}, + {"date", "DateTime$date", "func(dt:DateTime,timezone=!Text -> Text)"}, + {"format", "DateTime$format", "func(dt:DateTime,format=\"%Y-%m-%dT%H:%M:%S%z\",timezone=!Text -> Text)"}, + {"from_unix_timestamp", "DateTime$from_unix_timestamp", "func(timestamp:Int64 -> DateTime)"}, + {"get", "DateTime$get", "func(dt:DateTime,year,month,day,hour,minute,second,nanosecond,weekday=!&Int,timezone=!Text)"}, + {"get_local_timezone", "DateTime$get_local_timezone", "func(->Text)"}, + {"hours_till", "DateTime$hours_till", "func(now,then:DateTime -> Num)"}, + {"minutes_till", "DateTime$minutes_till", "func(now,then:DateTime -> Num)"}, + {"new", "DateTime$new", "func(year,month,day:Int,hour,minute=0,second=0.0,timezone=!Text -> DateTime)"}, + {"parse", "DateTime$parse", "func(text:Text, format=\"%Y-%m-%dT%H:%M:%S%z\" -> DateTime?)"}, + {"relative", "DateTime$relative", "func(dt:DateTime,relative_to=DateTime.now(),timezone=!Text -> Text)"}, + {"seconds_till", "DateTime$seconds_till", "func(now:DateTime,then:DateTime -> Num)"}, {"set_local_timezone", "DateTime$set_local_timezone", "func(timezone=!Text)"}, - {"time", "DateTime$time", "func(dt:DateTime,seconds=no,am_pm=yes,timezone=!Text)->Text"}, - {"unix_timestamp", "DateTime$unix_timestamp", "func(dt:DateTime)->Int64"}, + {"time", "DateTime$time", "func(dt:DateTime,seconds=no,am_pm=yes,timezone=!Text -> Text)"}, + {"unix_timestamp", "DateTime$unix_timestamp", "func(dt:DateTime -> Int64)"}, )}, {"Path", Type(TextType, .lang="Path", .env=namespace_env(env, "Path")), "Text_t", "Text$info", TypedArray(ns_entry_t, {"append", "Path$append", "func(path:Path, text:Text, permissions=0o644[32])"}, {"append_bytes", "Path$append_bytes", "func(path:Path, bytes:[Byte], permissions=0o644[32])"}, - {"base_name", "Path$base_name", "func(path:Path)->Text"}, - {"by_line", "Path$by_line", "func(path:Path)->(func()->Text?)?"}, - {"children", "Path$children", "func(path:Path, include_hidden=no)->[Path]"}, + {"base_name", "Path$base_name", "func(path:Path -> Text)"}, + {"by_line", "Path$by_line", "func(path:Path -> func(->Text?)?)"}, + {"children", "Path$children", "func(path:Path, include_hidden=no -> [Path])"}, {"create_directory", "Path$create_directory", "func(path:Path, permissions=0o755[32])"}, - {"escape_int", "Int$value_as_text", "func(i:Int)->Path"}, - {"escape_path", "Path$escape_path", "func(path:Path)->Path"}, - {"escape_text", "Path$escape_text", "func(text:Text)->Path"}, - {"exists", "Path$exists", "func(path:Path)->Bool"}, - {"extension", "Path$extension", "func(path:Path, full=yes)->Text"}, - {"files", "Path$children", "func(path:Path, include_hidden=no)->[Path]"}, - {"is_directory", "Path$is_directory", "func(path:Path, follow_symlinks=yes)->Bool"}, - {"is_file", "Path$is_file", "func(path:Path, follow_symlinks=yes)->Bool"}, - {"is_pipe", "Path$is_pipe", "func(path:Path, follow_symlinks=yes)->Bool"}, - {"is_socket", "Path$is_socket", "func(path:Path, follow_symlinks=yes)->Bool"}, - {"is_symlink", "Path$is_symlink", "func(path:Path)->Bool"}, - {"parent", "Path$parent", "func(path:Path)->Path"}, - {"read", "Path$read", "func(path:Path)->Text?"}, - {"read_bytes", "Path$read_bytes", "func(path:Path)->[Byte]?"}, - {"relative", "Path$relative", "func(path:Path, relative_to=(./))->Path"}, + {"escape_int", "Int$value_as_text", "func(i:Int -> Path)"}, + {"escape_path", "Path$escape_path", "func(path:Path -> Path)"}, + {"escape_text", "Path$escape_text", "func(text:Text -> Path)"}, + {"exists", "Path$exists", "func(path:Path -> Bool)"}, + {"extension", "Path$extension", "func(path:Path, full=yes -> Text)"}, + {"files", "Path$children", "func(path:Path, include_hidden=no -> [Path])"}, + {"is_directory", "Path$is_directory", "func(path:Path, follow_symlinks=yes -> Bool)"}, + {"is_file", "Path$is_file", "func(path:Path, follow_symlinks=yes -> Bool)"}, + {"is_pipe", "Path$is_pipe", "func(path:Path, follow_symlinks=yes -> Bool)"}, + {"is_socket", "Path$is_socket", "func(path:Path, follow_symlinks=yes -> Bool)"}, + {"is_symlink", "Path$is_symlink", "func(path:Path -> Bool)"}, + {"parent", "Path$parent", "func(path:Path -> Path)"}, + {"read", "Path$read", "func(path:Path -> Text?)"}, + {"read_bytes", "Path$read_bytes", "func(path:Path -> [Byte]?)"}, + {"relative", "Path$relative", "func(path:Path, relative_to=(./) -> Path)"}, {"remove", "Path$remove", "func(path:Path, ignore_missing=no)"}, - {"resolved", "Path$resolved", "func(path:Path, relative_to=(./))->Path"}, - {"subdirectories", "Path$children", "func(path:Path, include_hidden=no)->[Path]"}, - {"unique_directory", "Path$unique_directory", "func(path:Path)->Path"}, + {"resolved", "Path$resolved", "func(path:Path, relative_to=(./) -> Path)"}, + {"subdirectories", "Path$children", "func(path:Path, include_hidden=no -> [Path])"}, + {"unique_directory", "Path$unique_directory", "func(path:Path -> Path)"}, {"write", "Path$write", "func(path:Path, text:Text, permissions=0o644[32])"}, {"write_bytes", "Path$write_bytes", "func(path:Path, bytes:[Byte], permissions=0o644[32])"}, - {"write_unique", "Path$write_unique", "func(path:Path, text:Text)->Path"}, - {"write_unique_bytes", "Path$write_unique_bytes", "func(path:Path, bytes:[Byte])->Path"}, + {"write_unique", "Path$write_unique", "func(path:Path, text:Text -> Path)"}, + {"write_unique_bytes", "Path$write_unique_bytes", "func(path:Path, bytes:[Byte] -> Path)"}, - {"modified", "Path$modified", "func(path:Path, follow_symlinks=yes)->DateTime?"}, - {"accessed", "Path$accessed", "func(path:Path, follow_symlinks=yes)->DateTime?"}, - {"changed", "Path$changed", "func(path:Path, follow_symlinks=yes)->DateTime?"}, + {"modified", "Path$modified", "func(path:Path, follow_symlinks=yes -> DateTime?)"}, + {"accessed", "Path$accessed", "func(path:Path, follow_symlinks=yes -> DateTime?)"}, + {"changed", "Path$changed", "func(path:Path, follow_symlinks=yes -> DateTime?)"}, // Text methods: - {"ends_with", "Text$ends_with", "func(path:Path, suffix:Text)->Bool"}, - {"has", "Text$has", "func(path:Path, pattern:Pattern)->Bool"}, - {"matches", "Text$matches", "func(path:Path, pattern:Pattern)->[Text]?"}, - {"replace", "Text$replace", "func(path:Path, pattern:Pattern, replacement:Text, backref=$/\\/, recursive=yes)->Path"}, - {"replace_all", "Text$replace_all", "func(path:Path, replacements:{Pattern:Text}, backref=$/\\/, recursive=yes)->Path"}, - {"starts_with", "Text$starts_with", "func(path:Path, prefix:Text)->Bool"}, + {"ends_with", "Text$ends_with", "func(path:Path, suffix:Text -> Bool)"}, + {"has", "Text$has", "func(path:Path, pattern:Pattern -> Bool)"}, + {"matches", "Text$matches", "func(path:Path, pattern:Pattern -> [Text]?)"}, + {"replace", "Text$replace", "func(path:Path, pattern:Pattern, replacement:Text, backref=$/\\/, recursive=yes -> Path)"}, + {"replace_all", "Text$replace_all", "func(path:Path, replacements:{Pattern:Text}, backref=$/\\/, recursive=yes -> Path)"}, + {"starts_with", "Text$starts_with", "func(path:Path, prefix:Text -> Bool)"}, )}, {"Shell", Type(TextType, .lang="Shell", .env=namespace_env(env, "Shell")), "Shell_t", "Shell$info", TypedArray(ns_entry_t, - {"by_line", "Shell$by_line", "func(command:Shell)->(func()->Text?)?"}, - {"escape_int", "Int$value_as_text", "func(i:Int)->Shell"}, - {"escape_text", "Shell$escape_text", "func(text:Text)->Shell"}, - {"escape_text_array", "Shell$escape_text_array", "func(texts:[Text])->Shell"}, - {"run_bytes", "Shell$run", "func(command:Shell)->[Byte]?"}, - {"run", "Shell$run", "func(command:Shell)->Text?"}, + {"by_line", "Shell$by_line", "func(command:Shell -> func(->Text?)?)"}, + {"escape_int", "Int$value_as_text", "func(i:Int -> Shell)"}, + {"escape_text", "Shell$escape_text", "func(text:Text -> Shell)"}, + {"escape_text_array", "Shell$escape_text_array", "func(texts:[Text] -> Shell)"}, + {"run_bytes", "Shell$run", "func(command:Shell -> [Byte]?)"}, + {"run", "Shell$run", "func(command:Shell -> Text?)"}, )}, {"Text", TEXT_TYPE, "Text_t", "Text$info", TypedArray(ns_entry_t, - {"as_c_string", "Text$as_c_string", "func(text:Text)->CString"}, - {"codepoint_names", "Text$codepoint_names", "func(text:Text)->[Text]"}, - {"ends_with", "Text$ends_with", "func(text,suffix:Text)->Bool"}, - {"find", "Text$find", "func(text:Text, pattern:Pattern, start=1, length=!&Int64)->Int"}, - {"find_all", "Text$find_all", "func(text:Text, pattern:Pattern)->[Text]"}, - {"from_bytes", "Text$from_bytes", "func(bytes:[Byte])->Text"}, - {"from_c_string", "Text$from_str", "func(str:CString)->Text"}, - {"from_codepoint_names", "Text$from_codepoint_names", "func(codepoint_names:[Text])->Text"}, - {"from_codepoints", "Text$from_codepoints", "func(codepoints:[Int32])->Text"}, - {"without_escaping", "Path$cleanup", "func(text:Text)->Path"}, - {"has", "Text$has", "func(text:Text, pattern:Pattern)->Bool"}, - {"join", "Text$join", "func(glue:Text, pieces:[Text])->Text"}, - {"lines", "Text$lines", "func(text:Text)->[Text]"}, - {"lower", "Text$lower", "func(text:Text)->Text"}, - {"map", "Text$map", "func(text:Text, pattern:Pattern, fn:func(text:Text)->Text)->Text"}, - {"matches", "Text$matches", "func(text:Text, pattern:Pattern)->[Text]?"}, - {"quoted", "Text$quoted", "func(text:Text, color=no)->Text"}, - {"repeat", "Text$repeat", "func(text:Text, count:Int)->Text"}, - {"replace", "Text$replace", "func(text:Text, pattern:Pattern, replacement:Text, backref=$/\\/, recursive=yes)->Text"}, - {"replace_all", "Text$replace_all", "func(text:Text, replacements:{Pattern:Text}, backref=$/\\/, recursive=yes)->Text"}, - {"slice", "Text$slice", "func(text:Text, from=1, to=-1)->Text"}, - {"split", "Text$split", "func(text:Text, pattern=$Pattern'')->[Text]"}, - {"starts_with", "Text$starts_with", "func(text,prefix:Text)->Bool"}, - {"title", "Text$title", "func(text:Text)->Text"}, - {"trim", "Text$trim", "func(text:Text, pattern=$/{whitespace}/, trim_left=yes, trim_right=yes)->Text"}, - {"upper", "Text$upper", "func(text:Text)->Text"}, - {"utf32_codepoints", "Text$utf32_codepoints", "func(text:Text)->[Int32]"}, - {"utf8_bytes", "Text$utf8_bytes", "func(text:Text)->[Byte]"}, + {"as_c_string", "Text$as_c_string", "func(text:Text -> CString)"}, + {"codepoint_names", "Text$codepoint_names", "func(text:Text -> [Text])"}, + {"ends_with", "Text$ends_with", "func(text,suffix:Text -> Bool)"}, + {"find", "Text$find", "func(text:Text, pattern:Pattern, start=1, length=!&Int64 -> Int)"}, + {"find_all", "Text$find_all", "func(text:Text, pattern:Pattern -> [Text])"}, + {"from_bytes", "Text$from_bytes", "func(bytes:[Byte] -> Text)"}, + {"from_c_string", "Text$from_str", "func(str:CString -> Text)"}, + {"from_codepoint_names", "Text$from_codepoint_names", "func(codepoint_names:[Text] -> Text)"}, + {"from_codepoints", "Text$from_codepoints", "func(codepoints:[Int32] -> Text)"}, + {"without_escaping", "Path$cleanup", "func(text:Text -> Path)"}, + {"has", "Text$has", "func(text:Text, pattern:Pattern -> Bool)"}, + {"join", "Text$join", "func(glue:Text, pieces:[Text] -> Text)"}, + {"lines", "Text$lines", "func(text:Text -> [Text])"}, + {"lower", "Text$lower", "func(text:Text -> Text)"}, + {"map", "Text$map", "func(text:Text, pattern:Pattern, fn:func(text:Text -> Text) -> Text)"}, + {"matches", "Text$matches", "func(text:Text, pattern:Pattern -> [Text]?)"}, + {"quoted", "Text$quoted", "func(text:Text, color=no -> Text)"}, + {"repeat", "Text$repeat", "func(text:Text, count:Int -> Text)"}, + {"replace", "Text$replace", "func(text:Text, pattern:Pattern, replacement:Text, backref=$/\\/, recursive=yes -> Text)"}, + {"replace_all", "Text$replace_all", "func(text:Text, replacements:{Pattern:Text}, backref=$/\\/, recursive=yes -> Text)"}, + {"slice", "Text$slice", "func(text:Text, from=1, to=-1 -> Text)"}, + {"split", "Text$split", "func(text:Text, pattern=$Pattern'' -> [Text])"}, + {"starts_with", "Text$starts_with", "func(text,prefix:Text -> Bool)"}, + {"title", "Text$title", "func(text:Text -> Text)"}, + {"trim", "Text$trim", "func(text:Text, pattern=$/{whitespace}/, trim_left=yes, trim_right=yes -> Text)"}, + {"upper", "Text$upper", "func(text:Text -> Text)"}, + {"utf32_codepoints", "Text$utf32_codepoints", "func(text:Text -> [Int32])"}, + {"utf8_bytes", "Text$utf8_bytes", "func(text:Text -> [Byte])"}, )}, {"Thread", THREAD_TYPE, "Thread_t", "Thread", TypedArray(ns_entry_t, - {"new", "Thread$new", "func(fn:func())->Thread"}, + {"new", "Thread$new", "func(fn:func() -> Thread)"}, {"cancel", "Thread$cancel", "func(thread:Thread)"}, {"join", "Thread$join", "func(thread:Thread)"}, {"detach", "Thread$detach", "func(thread:Thread)"}, diff --git a/examples/game/game.tm b/examples/game/game.tm index c7d843e..81aed45 100644 --- a/examples/game/game.tm +++ b/examples/game/game.tm @@ -6,7 +6,7 @@ use use ./world.tm func main(map=(./map.txt)): - extern InitWindow:func(w:Int32, h:Int32, title:CString)->Void + extern InitWindow:func(w:Int32, h:Int32, title:CString) InitWindow(1600, 900, "raylib [core] example - 2d camera") map_contents := map:read() or exit("Could not find the game map: $map") @@ -16,10 +16,10 @@ func main(map=(./map.txt)): extern SetTargetFPS:func(fps:Int32) SetTargetFPS(60) - extern WindowShouldClose:func()->Bool + extern WindowShouldClose:func(->Bool) while not WindowShouldClose(): - extern GetFrameTime:func()->Num32 + extern GetFrameTime:func(->Num32) dt := GetFrameTime() World.CURRENT:update(Num(dt)) diff --git a/examples/game/world.tm b/examples/game/world.tm index 6208d1c..71c14bf 100644 --- a/examples/game/world.tm +++ b/examples/game/world.tm @@ -6,7 +6,7 @@ use ./color.tm use ./box.tm # Return a displacement relative to `a` that will push it out of `b` -func solve_overlap(a_pos:Vec2, a_size:Vec2, b_pos:Vec2, b_size:Vec2)->Vec2: +func solve_overlap(a_pos:Vec2, a_size:Vec2, b_pos:Vec2, b_size:Vec2 -> Vec2): a_left := a_pos.x a_right := a_pos.x + a_size.x a_top := a_pos.y diff --git a/examples/http/http.tm b/examples/http/http.tm index a4ded7d..a1bcccc 100644 --- a/examples/http/http.tm +++ b/examples/http/http.tm @@ -7,7 +7,7 @@ struct HTTPResponse(code:Int, body:Text) enum _Method(GET, POST, PUT, PATCH, DELETE) -func _send(method:_Method, url:Text, data:Text?, headers=[:Text])->HTTPResponse: +func _send(method:_Method, url:Text, data:Text?, headers=[:Text] -> HTTPResponse): chunks := @[:Text] save_chunk := func(chunk:CString, size:Int64, n:Int64): chunks:insert(inline C:Text { @@ -69,16 +69,16 @@ func _send(method:_Method, url:Text, data:Text?, headers=[:Text])->HTTPResponse: } return HTTPResponse(code, "":join(chunks)) -func get(url:Text, headers=[:Text])->HTTPResponse: +func get(url:Text, headers=[:Text] -> HTTPResponse): return _send(GET, url, !Text, headers) -func post(url:Text, data="", headers=["Content-Type: application/json", "Accept: application/json"])->HTTPResponse: +func post(url:Text, data="", headers=["Content-Type: application/json", "Accept: application/json"] -> HTTPResponse): return _send(POST, url, data, headers) -func put(url:Text, data="", headers=["Content-Type: application/json", "Accept: application/json"])->HTTPResponse: +func put(url:Text, data="", headers=["Content-Type: application/json", "Accept: application/json"] -> HTTPResponse): return _send(PUT, url, data, headers) -func delete(url:Text, data=!Text, headers=["Content-Type: application/json", "Accept: application/json"])->HTTPResponse: +func delete(url:Text, data=!Text, headers=["Content-Type: application/json", "Accept: application/json"] -> HTTPResponse): return _send(DELETE, url, data, headers) func main(): diff --git a/examples/ini/ini.tm b/examples/ini/ini.tm index 37692ca..4e5ec77 100644 --- a/examples/ini/ini.tm +++ b/examples/ini/ini.tm @@ -6,7 +6,7 @@ _HELP := " $_USAGE " -func parse_ini(path:Path)->{Text:{Text:Text}}: +func parse_ini(path:Path -> {Text:{Text:Text}}): text := path:read() or exit("Could not read INI file: $\[31;1]$(path.text_content)$\[]") sections := {:Text:@{Text:Text}} current_section := @{:Text:Text} diff --git a/examples/learnxiny.tm b/examples/learnxiny.tm index f003167..ed8e259 100644 --- a/examples/learnxiny.tm +++ b/examples/learnxiny.tm @@ -211,12 +211,12 @@ func main(): # Functions must be declared at the top level of a file and must specify the # types of all of their arguments and return value (if any): -func add(x:Int, y:Int)->Int: +func add(x:Int, y:Int -> Int): return x + y # Default values for arguments can be provided in place of a type (the type is # inferred from the default value): -func show_both(first:Int, second=0)->Text: +func show_both(first:Int, second=0 -> Text): return "first=$first second=$second" func demo_keyword_args(): @@ -241,7 +241,7 @@ func takes_many_types( table_of_text_to_bools:{Text:Bool}, pointer_to_mutable_array_of_ints:@[Int], optional_int:Int?, - function_from_int_to_text:func(x:Int)->Text, + function_from_int_to_text:func(x:Int -> Text), ): pass @@ -259,7 +259,7 @@ struct Person(name:Text, age:Int): self.age += amount # Methods don't have to take a Person as their first argument: - func get_cool_name()->Text: + func get_cool_name(->Text): return "Blade" func demo_structs(): @@ -304,7 +304,7 @@ enum Shape( ): # Just like with structs, you define methods and constants inside a level # of indentation: - func get_area(self:Shape)->Num: + func get_area(self:Shape->Num): # In order to work with an enum, it's most often handy to use a 'when' # statement to get the internal values: when self is Point: diff --git a/examples/log/log.tm b/examples/log/log.tm index 42df072..f537b85 100644 --- a/examples/log/log.tm +++ b/examples/log/log.tm @@ -5,7 +5,7 @@ timestamp_format := CString("%F %T") logfiles := {:Path} -func _timestamp()->Text: +func _timestamp(->Text): c_str := inline C:CString { char *str = GC_MALLOC_ATOMIC(20); time_t t; time(&t); diff --git a/examples/tomodeps/tomodeps.tm b/examples/tomodeps/tomodeps.tm index 9418ba6..907734a 100644 --- a/examples/tomodeps/tomodeps.tm +++ b/examples/tomodeps/tomodeps.tm @@ -9,7 +9,7 @@ _HELP := " enum Dependency(File(path:Path), Module(name:Text)) -func _get_file_dependencies(file:Path)->{Dependency}: +func _get_file_dependencies(file:Path -> {Dependency}): if not file:is_file(): !! Could not read file: $file return {:Dependency} @@ -55,12 +55,12 @@ func _build_dependency_graph(dep:Dependency, dependencies:&{Dependency:{Dependen for dep2 in dep_deps: _build_dependency_graph(dep2, dependencies) -func get_dependency_graph(dep:Dependency)->{Dependency:{Dependency}}: +func get_dependency_graph(dep:Dependency -> {Dependency:{Dependency}}): graph := {:Dependency:{Dependency}} _build_dependency_graph(dep, &graph) return graph -func _printable_name(dep:Dependency)->Text: +func _printable_name(dep:Dependency -> Text): when dep is Module(module): return "$(\x1b)[34;1m$module$(\x1b)[m" is File(f): diff --git a/examples/vectors/vectors.tm b/examples/vectors/vectors.tm index 8560f9d..696bef1 100644 --- a/examples/vectors/vectors.tm +++ b/examples/vectors/vectors.tm @@ -2,32 +2,32 @@ struct Vec2(x,y:Num): ZERO := Vec2(0, 0) - func plus(a,b:Vec2; inline)->Vec2: + func plus(a,b:Vec2->Vec2; inline): return Vec2(a.x+b.x, a.y+b.y) - func minus(a,b:Vec2; inline)->Vec2: + func minus(a,b:Vec2->Vec2; inline): return Vec2(a.x-b.x, a.y-b.y) - func times(a,b:Vec2; inline)->Vec2: + func times(a,b:Vec2->Vec2; inline): return Vec2(a.x*b.x, a.y*b.y) - func dot(a,b:Vec2; inline)->Num: + func dot(a,b:Vec2->Num; inline): return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) - func cross(a,b:Vec2; inline)->Num: + func cross(a,b:Vec2->Num; inline): return a.x*b.y - a.y*b.x - func scaled_by(v:Vec2, k:Num; inline)->Vec2: + func scaled_by(v:Vec2, k:Num->Vec2; inline): return Vec2(v.x*k, v.y*k) - func divided_by(v:Vec2, divisor:Num; inline)->Vec2: + func divided_by(v:Vec2, divisor:Num->Vec2; inline): return Vec2(v.x/divisor, v.y/divisor) - func length(v:Vec2; inline)->Num: + func length(v:Vec2->Num; inline): return (v.x*v.x + v.y*v.y):sqrt() - func dist(a,b:Vec2; inline)->Num: + func dist(a,b:Vec2->Num; inline): return a:minus(b):length() - func angle(v:Vec2; inline)->Num: + func angle(v:Vec2->Num; inline): return Num.atan2(v.y, v.x) - func norm(v:Vec2; inline)->Vec2: + func norm(v:Vec2->Vec2; inline): if v.x == 0 and v.y == 0: return v len := v:length() return Vec2(v.x/len, v.y/len) - func mix(a,b:Vec2, amount:Num)->Vec2: + func mix(a,b:Vec2, amount:Num -> Vec2): return Vec2( amount:mix(a.x, b.x), amount:mix(a.y, b.y), @@ -35,30 +35,30 @@ struct Vec2(x,y:Num): struct Vec3(x,y,z:Num): ZERO := Vec3(0, 0, 0) - func plus(a,b:Vec3; inline)->Vec3: + func plus(a,b:Vec3->Vec3; inline): return Vec3(a.x+b.x, a.y+b.y, a.z+b.z) - func minus(a,b:Vec3; inline)->Vec3: + func minus(a,b:Vec3->Vec3; inline): return Vec3(a.x-b.x, a.y-b.y, a.z-b.z) - func times(a,b:Vec3; inline)->Vec3: + func times(a,b:Vec3->Vec3; inline): return Vec3(a.x*b.x, a.y*b.y, a.z*b.z) - func dot(a,b:Vec3; inline)->Num: + func dot(a,b:Vec3->Num; inline): return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) + (a.z-b.z)*(a.z-b.z) - func cross(a,b:Vec3; inline)->Vec3: + func cross(a,b:Vec3->Vec3; inline): return Vec3(a.y*b.z - a.z-b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x) - func scaled_by(v:Vec3, k:Num; inline)->Vec3: + func scaled_by(v:Vec3, k:Num->Vec3; inline): return Vec3(v.x*k, v.y*k, v.z*k) - func divided_by(v:Vec3, divisor:Num; inline)->Vec3: + func divided_by(v:Vec3, divisor:Num->Vec3; inline): return Vec3(v.x/divisor, v.y/divisor, v.z/divisor) - func length(v:Vec3; inline)->Num: + func length(v:Vec3->Num; inline): return (v.x*v.x + v.y*v.y + v.z*v.z):sqrt() - func dist(a,b:Vec3; inline)->Num: + func dist(a,b:Vec3->Num; inline): return a:minus(b):length() - func norm(v:Vec3; inline)->Vec3: + func norm(v:Vec3->Vec3; inline): if v.x == 0 and v.y == 0 and v.z == 0: return v len := v:length() return Vec3(v.x/len, v.y/len, v.z/len) - func mix(a,b:Vec3, amount:Num)->Vec3: + func mix(a,b:Vec3, amount:Num -> Vec3): return Vec3( amount:mix(a.x, b.x), amount:mix(a.y, b.y), @@ -68,46 +68,46 @@ struct Vec3(x,y,z:Num): struct IVec2(x,y:Int): ZERO := IVec2(0, 0) - func plus(a,b:IVec2; inline)->IVec2: + func plus(a,b:IVec2->IVec2; inline): return IVec2(a.x+b.x, a.y+b.y) - func minus(a,b:IVec2; inline)->IVec2: + func minus(a,b:IVec2->IVec2; inline): return IVec2(a.x-b.x, a.y-b.y) - func times(a,b:IVec2; inline)->IVec2: + func times(a,b:IVec2->IVec2; inline): return IVec2(a.x*b.x, a.y*b.y) - func dot(a,b:IVec2; inline)->Int: + func dot(a,b:IVec2->Int; inline): return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) - func cross(a,b:IVec2; inline)->Int: + func cross(a,b:IVec2->Int; inline): return a.x*b.y - a.y*b.x - func scaled_by(v:IVec2, k:Int; inline)->IVec2: + func scaled_by(v:IVec2, k:Int->IVec2; inline): return IVec2(v.x*k, v.y*k) - func divided_by(v:IVec2, divisor:Int; inline)->IVec2: + func divided_by(v:IVec2, divisor:Int->IVec2; inline): return IVec2(v.x/divisor, v.y/divisor) - func length(v:IVec2; inline)->Num: + func length(v:IVec2->Num; inline): return Num.sqrt(v.x*v.x + v.y*v.y) - func dist(a,b:IVec2; inline)->Num: + func dist(a,b:IVec2->Num; inline): return a:minus(b):length() - func angle(v:IVec2; inline)->Num: + func angle(v:IVec2->Num; inline): return Num.atan2(v.y, v.x) struct IVec3(x,y,z:Int): ZERO := IVec3(0, 0, 0) - func plus(a,b:IVec3; inline)->IVec3: + func plus(a,b:IVec3->IVec3; inline): return IVec3(a.x+b.x, a.y+b.y, a.z+b.z) - func minus(a,b:IVec3; inline)->IVec3: + func minus(a,b:IVec3->IVec3; inline): return IVec3(a.x-b.x, a.y-b.y, a.z-b.z) - func times(a,b:IVec3; inline)->IVec3: + func times(a,b:IVec3->IVec3; inline): return IVec3(a.x*b.x, a.y*b.y, a.z*b.z) - func dot(a,b:IVec3; inline)->Int: + func dot(a,b:IVec3->Int; inline): return (a.x-b.x)*(a.x-b.x) + (a.y-b.y)*(a.y-b.y) + (a.z-b.z)*(a.z-b.z) - func cross(a,b:IVec3; inline)->IVec3: + func cross(a,b:IVec3->IVec3; inline): return IVec3(a.y*b.z - a.z-b.y, a.z*b.x - a.x*b.z, a.x*b.y - a.y*b.x) - func scaled_by(v:IVec3, k:Int; inline)->IVec3: + func scaled_by(v:IVec3, k:Int->IVec3; inline): return IVec3(v.x*k, v.y*k, v.z*k) - func divided_by(v:IVec3, divisor:Int; inline)->IVec3: + func divided_by(v:IVec3, divisor:Int->IVec3; inline): return IVec3(v.x/divisor, v.y/divisor, v.z/divisor) - func length(v:IVec3; inline)->Num: + func length(v:IVec3->Num; inline): return Num.sqrt(v.x*v.x + v.y*v.y + v.z*v.z) - func dist(a,b:IVec3; inline)->Num: + func dist(a,b:IVec3->Num; inline): return a:minus(b):length() func main(): diff --git a/examples/wrap/wrap.tm b/examples/wrap/wrap.tm index a89d8b4..ced8aab 100644 --- a/examples/wrap/wrap.tm +++ b/examples/wrap/wrap.tm @@ -13,7 +13,7 @@ HELP := " UNICODE_HYPHEN := \{hyphen} -func unwrap(text:Text, preserve_paragraphs=yes, hyphen=UNICODE_HYPHEN)->Text: +func unwrap(text:Text, preserve_paragraphs=yes, hyphen=UNICODE_HYPHEN -> Text): if preserve_paragraphs: paragraphs := text:split($/{2+ nl}/) if paragraphs.length > 1: @@ -21,7 +21,7 @@ func unwrap(text:Text, preserve_paragraphs=yes, hyphen=UNICODE_HYPHEN)->Text: return text:replace($/$(hyphen)$(\n)/, "") -func wrap(text:Text, width:Int, min_split=3, hyphen="-")->Text: +func wrap(text:Text, width:Int, min_split=3, hyphen="-" -> Text): if width <= 0: fail("Width must be a positive integer, not $width") @@ -71,7 +71,7 @@ func wrap(text:Text, width:Int, min_split=3, hyphen="-")->Text: return \n:join(lines) -func _can_fit_word(line:Text, letters:[Text], width:Int; inline)->Bool: +func _can_fit_word(line:Text, letters:[Text], width:Int -> Bool; inline): if line == "": return letters.length <= width else: diff --git a/parse.c b/parse.c index f07f3ba..5d2cc6c 100644 --- a/parse.c +++ b/parse.c @@ -602,9 +602,9 @@ type_ast_t *parse_func_type(parse_ctx_t *ctx, const char *pos) { spaces(&pos); if (!match(&pos, "(")) return NULL; arg_ast_t *args = parse_args(ctx, &pos); - expect_closing(ctx, &pos, ")", "I wasn't able to parse the rest of this function type"); spaces(&pos); type_ast_t *ret = match(&pos, "->") ? optional(ctx, &pos, parse_type) : NULL; + expect_closing(ctx, &pos, ")", "I wasn't able to parse the rest of this function type"); return NewTypeAST(ctx->file, start, pos, FunctionTypeAST, .args=args, .ret=ret); } @@ -691,6 +691,7 @@ type_ast_t *parse_non_optional_type(parse_ctx_t *ctx, const char *pos) { type_ast_t *parse_type(parse_ctx_t *ctx, const char *pos) { const char *start = pos; type_ast_t *type = parse_non_optional_type(ctx, pos); + if (!type) return NULL; pos = type->end; spaces(&pos); if (match(&pos, "?")) @@ -1548,10 +1549,12 @@ PARSER(parse_lambda) { return NULL; arg_ast_t *args = parse_args(ctx, &pos); spaces(&pos); + type_ast_t *ret = match(&pos, "->") ? optional(ctx, &pos, parse_type) : NULL; + spaces(&pos); expect_closing(ctx, &pos, ")", "I was expecting a ')' to finish this anonymous function's arguments"); ast_t *body = optional(ctx, &pos, parse_block); if (!body) body = NewAST(ctx->file, pos, pos, Block, .statements=NULL); - return NewAST(ctx->file, start, pos, Lambda, .id=ctx->next_lambda_id++, .args=args, .body=body); + return NewAST(ctx->file, start, pos, Lambda, .id=ctx->next_lambda_id++, .args=args, .ret_type=ret, .body=body); } PARSER(parse_null) { @@ -2242,6 +2245,8 @@ PARSER(parse_func_def) { if (!match(&pos, "(")) return NULL; arg_ast_t *args = parse_args(ctx, &pos); + spaces(&pos); + type_ast_t *ret_type = match(&pos, "->") ? optional(ctx, &pos, parse_type) : NULL; whitespace(&pos); bool is_inline = false; ast_t *cache_ast = NULL; @@ -2261,11 +2266,6 @@ PARSER(parse_func_def) { } expect_closing(ctx, &pos, ")", "I wasn't able to parse the rest of this function definition"); - type_ast_t *ret_type = NULL; - spaces(&pos); - if (match(&pos, "->")) - ret_type = optional(ctx, &pos, parse_type); - ast_t *body = expect(ctx, start, &pos, parse_block, "This function needs a body block"); return NewAST(ctx->file, start, pos, FunctionDef, diff --git a/test/corecursive_func.tm b/test/corecursive_func.tm index 168300d..b5f5f13 100644 --- a/test/corecursive_func.tm +++ b/test/corecursive_func.tm @@ -1,10 +1,10 @@ -func ping(x:Int)->[Text]: +func ping(x:Int->[Text]): if x > 0: return ["ping: $x"] ++ pong(x-1) else: return ["ping: $x"] -func pong(x:Int)->[Text]: +func pong(x:Int->[Text]): if x > 0: return ["pong: $x"] ++ ping(x-1) else: diff --git a/test/defer.tm b/test/defer.tm index 5d3c55b..911ed67 100644 --- a/test/defer.tm +++ b/test/defer.tm @@ -76,7 +76,7 @@ func defer_func(return_early=no): say("Finished defer_func") -func make_counter()->func()->Int: +func make_counter(->func(->Int)): i := 1 return func(): defer: i += 1 diff --git a/test/enums.tm b/test/enums.tm index 0699fc9..c2ffce4 100644 --- a/test/enums.tm +++ b/test/enums.tm @@ -1,6 +1,6 @@ enum Foo(Zero, One(x:Int), Two(x:Int, y:Int), Three(x:Int, y:Text, z:Bool), Four(x,y,z,w:Int), Last(t:Text)) -func choose_text(f:Foo)->Text: +func choose_text(f:Foo->Text): >> f when f is Zero: return "Zero" diff --git a/test/extern.tm b/test/extern.tm index 4823b21..ddd800d 100644 --- a/test/extern.tm +++ b/test/extern.tm @@ -1,4 +1,4 @@ -extern sqrt:func(n:Num)->Num +extern sqrt:func(n:Num->Num) func main(): >> sqrt(4) diff --git a/test/for.tm b/test/for.tm index 6ac77be..ae5f786 100644 --- a/test/for.tm +++ b/test/for.tm @@ -1,5 +1,5 @@ -func all_nums(nums:[Int])->Text: +func all_nums(nums:[Int] -> Text): result := "" for num in nums: result ++= "$num," @@ -7,7 +7,7 @@ func all_nums(nums:[Int])->Text: return "EMPTY" return result -func labeled_nums(nums:[Int])->Text: +func labeled_nums(nums:[Int] -> Text): result := "" for i,num in nums: result ++= "$i:$num," @@ -15,14 +15,14 @@ func labeled_nums(nums:[Int])->Text: return "EMPTY" return result -func table_str(t:{Text:Text})->Text: +func table_str(t:{Text:Text} -> Text): str := "" for k,v in t: str ++= "$k:$v," else: return "EMPTY" return str -func table_key_str(t:{Text:Text})->Text: +func table_key_str(t:{Text:Text} -> Text): str := "" for k in t: str ++= "$k," diff --git a/test/functions.tm b/test/functions.tm index 426c33b..22d950d 100644 --- a/test/functions.tm +++ b/test/functions.tm @@ -1,7 +1,7 @@ -func add(x:Int, y:Int)->Int: +func add(x:Int, y:Int -> Int): return x + y -func cached_heap(x:Int; cached)->@Int: +func cached_heap(x:Int->@Int; cached): return @x func main(): diff --git a/test/import.tm b/test/import.tm index 9362e08..a7b198b 100644 --- a/test/import.tm +++ b/test/import.tm @@ -1,10 +1,10 @@ vectors := use ../examples/vectors/vectors.tm use ./use_import.tm -func returns_vec()->vectors.Vec2: +func returns_vec(->vectors.Vec2): return vectors.Vec2(1, 2) -func returns_imported_type()->ImportedType: +func returns_imported_type(->ImportedType): return get_value() # Imported from ./use_import.tm func main(): diff --git a/test/iterators.tm b/test/iterators.tm index 6893c59..fca91b2 100644 --- a/test/iterators.tm +++ b/test/iterators.tm @@ -1,14 +1,14 @@ struct Pair(x:Text, y:Text) -func pairwise(strs:[Text])->func()->Pair?: +func pairwise(strs:[Text] -> func(->Pair?)): i := 1 return func(): if i + 1 > strs.length: return !Pair i += 1 return Pair(strs[i-1], strs[i])? -func range(first:Int, last:Int)->func()->Int?: +func range(first:Int, last:Int -> func(->Int?)): i := first return func(): if i > last: diff --git a/test/lambdas.tm b/test/lambdas.tm index 62b5fd3..d830a36 100644 --- a/test/lambdas.tm +++ b/test/lambdas.tm @@ -1,10 +1,10 @@ -func make_adder(x:Int)-> func(y:Int)->Int: +func make_adder(x:Int -> func(y:Int->Int)): return func(y:Int): x + y -func suffix_fn(fn:func(t:Text)->Text, suffix:Text)->func(t:Text)->Text: +func suffix_fn(fn:func(t:Text->Text), suffix:Text -> func(t:Text->Text)): return func(t:Text): fn(t)++suffix -func mul_func(n:Int, fn:func(x:Int)->Int)-> func(x:Int)->Int: +func mul_func(n:Int, fn:func(x:Int->Int) -> func(x:Int->Int)): return func(x:Int): n*fn(x) func main(): diff --git a/test/lang.tm b/test/lang.tm index 9a05eb1..b30bcbe 100644 --- a/test/lang.tm +++ b/test/lang.tm @@ -1,6 +1,6 @@ lang HTML: HEADER := $HTML"" - func escape(t:Text)->HTML: + func escape(t:Text->HTML): t = t:replace_all({ $/&/: "&", $/HTML: + func escape_int(i:Int->HTML): return HTML.without_escaping("$i") - func paragraph(content:HTML)->HTML: + func paragraph(content:HTML->HTML): return $HTML"

$content

" func main(): diff --git a/test/metamethods.tm b/test/metamethods.tm index 0b4bf87..5566b4e 100644 --- a/test/metamethods.tm +++ b/test/metamethods.tm @@ -1,47 +1,47 @@ struct Vec2(x,y:Int): - func plus(a,b:Vec2; inline)->Vec2: + func plus(a,b:Vec2 -> Vec2; inline): return Vec2(a.x+b.x, a.y+b.y) - func minus(a,b:Vec2; inline)->Vec2: + func minus(a,b:Vec2 -> Vec2; inline): return Vec2(a.x-b.x, a.y-b.y) - func dot(a,b:Vec2; inline)->Int: + func dot(a,b:Vec2 -> Int; inline): return a.x*b.x + a.y*b.y - func scaled_by(a:Vec2, k:Int; inline)->Vec2: + func scaled_by(a:Vec2, k:Int -> Vec2; inline): return Vec2(a.x*k, a.y*k) - func times(a,b:Vec2; inline)->Vec2: + func times(a,b:Vec2 -> Vec2; inline): return Vec2(a.x*b.x, a.y*b.y) - func divided_by(a:Vec2, k:Int; inline)->Vec2: + func divided_by(a:Vec2, k:Int -> Vec2; inline): return Vec2(a.x/k, a.y/k) - func negative(v:Vec2; inline)->Vec2: + func negative(v:Vec2 -> Vec2; inline): return Vec2(-v.x, -v.y) - func negated(v:Vec2; inline)->Vec2: + func negated(v:Vec2 -> Vec2; inline): return Vec2(not v.x, not v.y) - func bit_and(a,b:Vec2; inline)->Vec2: + func bit_and(a,b:Vec2 -> Vec2; inline): return Vec2(a.x and b.x, a.y and b.y) - func bit_or(a,b:Vec2; inline)->Vec2: + func bit_or(a,b:Vec2 -> Vec2; inline): return Vec2(a.x or b.x, a.y or b.y) - func bit_xor(a,b:Vec2; inline)->Vec2: + func bit_xor(a,b:Vec2 -> Vec2; inline): return Vec2(a.x xor b.x, a.y xor b.y) - func left_shifted(v:Vec2, bits:Int; inline)->Vec2: + func left_shifted(v:Vec2, bits:Int -> Vec2; inline): return Vec2(v.x >> bits, v.y >> bits) - func right_shifted(v:Vec2, bits:Int; inline)->Vec2: + func right_shifted(v:Vec2, bits:Int -> Vec2; inline): return Vec2(v.x << bits, v.y << bits) - func modulo(v:Vec2, modulus:Int; inline)->Vec2: + func modulo(v:Vec2, modulus:Int -> Vec2; inline): return Vec2(v.x mod modulus, v.y mod modulus) - func modulo1(v:Vec2, modulus:Int; inline)->Vec2: + func modulo1(v:Vec2, modulus:Int -> Vec2; inline): return Vec2(v.x mod1 modulus, v.y mod1 modulus) func main(): diff --git a/test/minmax.tm b/test/minmax.tm index c2f070f..fa0e8bd 100644 --- a/test/minmax.tm +++ b/test/minmax.tm @@ -1,6 +1,6 @@ struct Foo(x:Int, y:Int): - func len(f:Foo)->Num: + func len(f:Foo->Num): return Num.sqrt(f.x*f.x + f.y*f.y) func main(): diff --git a/test/optionals.tm b/test/optionals.tm index c0cc116..612ab76 100644 --- a/test/optionals.tm +++ b/test/optionals.tm @@ -1,73 +1,73 @@ struct Struct(x:Int, y:Text): - func maybe(should_i:Bool)->Struct?: + func maybe(should_i:Bool->Struct?): if should_i: return Struct(123, "hello") else: return !Struct enum Enum(X, Y(y:Int)): - func maybe(should_i:Bool)->Enum?: + func maybe(should_i:Bool->Enum?): if should_i: return Enum.Y(123) else: return !Enum -func maybe_int(should_i:Bool)->Int?: +func maybe_int(should_i:Bool->Int?): if should_i: return 123 else: return !Int -func maybe_int64(should_i:Bool)->Int64?: +func maybe_int64(should_i:Bool->Int64?): if should_i: return 123[64] else: return !Int64 -func maybe_array(should_i:Bool)->[Int]?: +func maybe_array(should_i:Bool->[Int]?): if should_i: return [10, 20, 30] else: return ![Int] -func maybe_bool(should_i:Bool)->Bool?: +func maybe_bool(should_i:Bool->Bool?): if should_i: return no else: return !Bool -func maybe_text(should_i:Bool)->Text?: +func maybe_text(should_i:Bool->Text?): if should_i: return "Hello" else: return !Text -func maybe_num(should_i:Bool)->Num?: +func maybe_num(should_i:Bool->Num?): if should_i: return 12.3 else: return !Num -func maybe_lambda(should_i:Bool)-> func()?: +func maybe_lambda(should_i:Bool-> func()?): if should_i: return func(): say("hi!") else: return !func() -func maybe_c_string(should_i:Bool)->CString?: +func maybe_c_string(should_i:Bool->CString?): if should_i: return ("hi":as_c_string())? else: return !CString -func maybe_channel(should_i:Bool)->|Int|?: +func maybe_channel(should_i:Bool->|Int|?): if should_i: return |:Int|? else: return !|Int| -func maybe_thread(should_i:Bool)->Thread?: +func maybe_thread(should_i:Bool->Thread?): if should_i: return Thread.new(func(): pass) else: diff --git a/test/use_import.tm b/test/use_import.tm index 979256b..714c26b 100644 --- a/test/use_import.tm +++ b/test/use_import.tm @@ -2,7 +2,7 @@ struct ImportedType(name:Text) needs_initializing := 999999999999999999 -func get_value()->ImportedType: +func get_value(->ImportedType): return ImportedType("Hello") func main(): diff --git a/typecheck.c b/typecheck.c index 0af0c23..a5d0d2e 100644 --- a/typecheck.c +++ b/typecheck.c @@ -1138,6 +1138,15 @@ type_t *get_type(env_t *env, ast_t *ast) if (ret->tag == AbortType) ret = Type(VoidType); + if (lambda->ret_type) { + type_t *declared = parse_type_ast(env, lambda->ret_type); + if (can_promote(ret, declared)) + ret = declared; + else + code_err(ast, "This function was declared to return a value of type %T, but actually returns a value of type %T", + declared, ret); + } + if (has_stack_memory(ret)) code_err(ast, "Functions can't return stack references because the reference may outlive its stack frame."); return Type(ClosureType, Type(FunctionType, .args=args, .ret=ret)); diff --git a/types.c b/types.c index 9407f95..ec1b66c 100644 --- a/types.c +++ b/types.c @@ -57,9 +57,8 @@ CORD type_to_cord(type_t *t) { if (arg->next) c = CORD_cat(c, ", "); } if (fn->ret && fn->ret->tag != VoidType) - c = CORD_all(c, ")->", type_to_cord(fn->ret)); - else - c = CORD_all(c, ")"); + c = CORD_all(c, "->", type_to_cord(fn->ret)); + c = CORD_all(c, ")"); return c; } case StructType: {