Private
Public Access
Use star for compile-time generic parameters
This commit is contained in:
1 parent
0d43f46803
commit
fe463c05cc
27 files changed
+125
-77
No files matched your search
@@ -90,7 +90,7 @@ type Count = s64
|
||||
var count := Count(4)
|
||||
```
|
||||
|
||||
An alias to an array, function type, `module`, or `void` has no constructor call. `any` and dependent `value::type` expressions require a generic function context and cannot be closed top-level aliases.
|
||||
An alias to an array, function type, `module`, or `void` has no constructor call. `*` and dependent `value::type` expressions require a generic function context and cannot be closed top-level aliases.
|
||||
|
||||
An alias cannot conflict with a built-in type, struct, function, handler, public standard-library name, or another alias.
|
||||
|
||||
@@ -200,7 +200,7 @@ Overload identity is the function name plus canonical parameter types and the va
|
||||
The compiler ranks matching calls in this order:
|
||||
|
||||
1. exact concrete parameters;
|
||||
2. an `any` specialization without construction;
|
||||
2. a `*` specialization without construction;
|
||||
3. fixed parameters with declared construction;
|
||||
4. variadic parameters.
|
||||
|
||||
@@ -250,7 +250,7 @@ A struct receives a generated constructor in field order. User functions can add
|
||||
|
||||
Constructor defaults and omitted call arguments do not change the Wasm call ABI. Copied DValue `none` uses Wasm core ABI 26. Future ABI changes must use a new ABI version.
|
||||
|
||||
`any` is compile-time polymorphism. It has no runtime representation. In a generic function, `parameter::type` names the concrete static type bound to an earlier `any` parameter. Use it for a later parameter or the function result. The compiler rejects the removed `type(parameter)` spelling.
|
||||
`*` is the compile-time generic marker. It has no runtime representation. In a generic function, `parameter::type` names the concrete static type bound to an earlier `*` parameter. Use it for a later parameter or the function result. The compiler rejects the removed `type(parameter)` spelling.
|
||||
|
||||
## 9. Collections and aggregates
|
||||
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
"as"
|
||||
],
|
||||
"genericTypes": [
|
||||
"any"
|
||||
"*"
|
||||
],
|
||||
"literals": [
|
||||
"false",
|
||||
@@ -395,8 +395,12 @@
|
||||
"match": "(?<![A-Za-z0-9_])(?:module|string|bool|dval|void|f32|f64|s16|s32|s64|u16|u32|u64|s8|u8)(?![A-Za-z0-9_])"
|
||||
},
|
||||
{
|
||||
"name": "storage.type.generic.capy",
|
||||
"match": "(?<![A-Za-z0-9_])(?:any)(?![A-Za-z0-9_])"
|
||||
"match": "(?<=:)\\s*(\\*)(?=\\s*[,)=])",
|
||||
"captures": {
|
||||
"1": {
|
||||
"name": "storage.type.generic.capy"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "entity.name.type.capy",
|
||||
|
||||
@@ -63,6 +63,16 @@ assertScope('print("capy") // note', "capy", "string.quoted.double.capy");
|
||||
assertScope('print("capy") // note', "note", "comment.line.double-slash.capy");
|
||||
assertScope("var value : u32 = 42", "42", "constant.numeric.integer.capy");
|
||||
assertScope("print(value)", "print", "entity.name.function.call.capy");
|
||||
for (const line of ["function same(first : *, second : first::type) first::type", "function same(first:*) first::type"]) {
|
||||
assertScope(line, "*", "storage.type.generic.capy");
|
||||
assertScope(line, "::", "keyword.operator.scope.capy");
|
||||
}
|
||||
for (const line of ["var product := left * right", "var product := left*right", "print({product: left * right})"]) {
|
||||
const result = assertScope(line, "*", "keyword.operator.arithmetic.capy");
|
||||
assert.ok(!scopesFor(result, line, "*").includes("storage.type.generic.capy"));
|
||||
}
|
||||
const ordinaryName = "var any := 1";
|
||||
assert.ok(!scopesFor(tokenize(ordinaryName), ordinaryName, "any").includes("storage.type.generic.capy"));
|
||||
|
||||
for (const line of [
|
||||
'<><p title="<?= caption ?>">Hello <?= value ?></p></>',
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ function test(x : s32, y : s32) s32 { // overload identity: test+s32,s32
|
||||
}
|
||||
|
||||
// polymorphic, instantiated at compile time if not already in namespace
|
||||
function test(x : any) x::type { // compile-time any is specialized and cached by its concrete parameter type
|
||||
function test(x : *) x::type { // The compiler specializes and caches this function by its concrete parameter type.
|
||||
return x*x // specialization fails at the callsite if * is not defined for x::type
|
||||
}
|
||||
|
||||
@@ -70,7 +70,7 @@ function print(xa : s32) {
|
||||
print("Hello World ", a) // pattern matching tries to find an exact match, if not found, it will try to find the best match that has implicit "as" conversions
|
||||
|
||||
// Deferred until after compiler phase 3: this requires partial compilation into a bounded compile-time workspace.
|
||||
function meta_programming_example(myvar : any) {
|
||||
function meta_programming_example(myvar : *) {
|
||||
#compile { // this will be executed at compile time, and can be used to generate code, or perform compile time calculations
|
||||
print("Polymorphic: ", myvar::type::type_name) // :: denotes type introspection and meta information about a variable
|
||||
// there can be arbitrary number of #compile and #callsite blocks in a function, and they will be executed in order of appearance
|
||||
|
||||
@@ -53,7 +53,7 @@ f84060af8de69766ce434a78ada90d732fe2e182b55f34f933ca4e276b5f3208 site_tests_cap
|
||||
05a9edb689e63226ad056c845375563642f61fe404c3ee772c02cee3646083d0 site_tests_capy-cross-target.capy.wasm
|
||||
dc5ba29db10e29ca2dd43ceb855b4593ec4d7682b7e3d0649bdeb0eb820f1cec site_tests_capy-cross-target.capy.wasm.source-map
|
||||
25d16c1b0eb1741ccfe495acd60529a121db3d4fbc0f194e0d1a44d40deb4bdc site_tests_capy-crypto-random.capy.wasm
|
||||
5fa47388e74ae09b67f448403e0c6d78f57f5ea5736e974f4bc733f1d488f4d0 site_tests_capy-crypto-random.capy.wasm.source-map
|
||||
768495624e4146c446ddffbb71f2b285df46372bb3818400ee3eb479a0ddea31 site_tests_capy-crypto-random.capy.wasm.source-map
|
||||
556fc959eeec32274324c31f82cd1b8fff9e4dca75ed1e2a378f0e77513dbb19 site_tests_capy-csrf.capy.wasm
|
||||
2b2c833274803ca7eafeb0a01d4f907eebcc80a49324282ffc0427c20fde1f53 site_tests_capy-csrf.capy.wasm.source-map
|
||||
52a39c6bccfcec345790452a4e1f71f34787a1f5082db84a841a231cd9f6c181 site_tests_capy-current-request.capy.wasm
|
||||
|
||||
@@ -56,7 +56,9 @@ def authoritative_words() -> dict[str, list[str]]:
|
||||
operator_words = {"as"}
|
||||
keywords -= operator_words
|
||||
|
||||
generic_types = set(re.findall(r"`(any)`", section(spec, "8. Functions, overloads, and constructors")))
|
||||
generic_types = set(re.findall(r"`(\*)`", section(spec, "8. Functions, overloads, and constructors")))
|
||||
if generic_types != {"*"}:
|
||||
raise RuntimeError("missing generic marker in the specification")
|
||||
literals = set(re.findall(r"`(none)`", section(spec, "1. Source files and tokens"))) | {"true", "false"}
|
||||
reserved = set(re.findall(r"`(emit)`", section(spec, "1. Source files and tokens")))
|
||||
|
||||
@@ -223,7 +225,7 @@ def grammar(words: dict[str, list[str]]) -> dict:
|
||||
]},
|
||||
"types": {"patterns": [
|
||||
{"name": "support.type.builtin.capy", "match": word_pattern(words["types"])},
|
||||
{"name": "storage.type.generic.capy", "match": word_pattern(words["genericTypes"])},
|
||||
{"match": r"(?<=:)\s*(\*)(?=\s*[,)=])", "captures": {"1": {"name": "storage.type.generic.capy"}}},
|
||||
{"name": "entity.name.type.capy", "match": r"(?<![A-Za-z0-9_])[A-Z][A-Za-z0-9_]*"},
|
||||
]},
|
||||
"constants": {"patterns": [{"name": "constant.language.capy", "match": word_pattern(words["literals"])}]},
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
directive: { pattern: /#(?:callsite|compile|exports|import)\b/, alias: 'keyword' },
|
||||
'handler-name': { pattern: /(\bfunction\s+)[A-Za-z_]\w*(?:\s*:\s*[A-Za-z_]\w*)?(?=\s*\()/, lookbehind: true, alias: 'function' },
|
||||
keyword: /\b(?:break|continue|else|for|function|host|if|return|struct|trace|type|var|while|as|capture|export)\b/,
|
||||
'class-name': /\b(?:any|bool|dval|f32|f64|module|s8|s16|s32|s64|u8|u16|u32|u64|string|void)\b/,
|
||||
'generic-type': { pattern: /(:\s*)\*(?=\s*[,)=])/, lookbehind: true, alias: 'class-name' },
|
||||
'class-name': /\b(?:bool|dval|f32|f64|module|s8|s16|s32|s64|u8|u16|u32|u64|string|void)\b/,
|
||||
boolean: /\b(?:true|false)\b/,
|
||||
constant: /\bnone\b/,
|
||||
function: /\b[A-Za-z_]\w*(?=\s*\()/,
|
||||
|
||||
@@ -164,9 +164,9 @@ int main()
|
||||
assert(capy::wasm::validate_bearer_unit(defaults.wasm, {.bearer_abi_version = "11"}).valid);
|
||||
assert(defaults.source_map.find("\t5\t") != std::string::npos);
|
||||
const auto dependent_type = capy::compile_bearer_unit(
|
||||
"function f(min : any, max : min::type) min::type { -> min }\n"
|
||||
"function legacy(value : any) value::type { -> value }\n"
|
||||
"function CLI(request : dval) { var value := f(1, 2); print(value, legacy(4)) }\n", options);
|
||||
"function f(min : *, max : min::type) min::type { -> min }\n"
|
||||
"function identity(value : *) value::type { -> value }\n"
|
||||
"function CLI(request : dval) { var value := f(1, 2); var dynamic : dval = {value: 4}; print(value, identity(dynamic), identity(-4 * 2), !false) }\n", options);
|
||||
assert(capy::wasm::validate_bearer_unit(dependent_type.wasm, {.bearer_abi_version = "11"}).valid);
|
||||
const auto reflection = capy::compile_bearer_unit(
|
||||
"struct Reflected { count : s32 }\n"
|
||||
@@ -180,10 +180,15 @@ int main()
|
||||
assert(metadata_only_bytes.find("MetadataOnly") != std::string::npos && metadata_only_bytes.find("count") != std::string::npos);
|
||||
assert(metadata_only_bytes.find("bearer_capy_reflect_struct") == std::string::npos);
|
||||
for (const auto& [source, expected] : {
|
||||
std::pair{"function f(min : any, max : min::type) min::type { -> min }\nfunction CLI(request : dval) { f(1, \"x\") }\n", "no overload f"},
|
||||
std::pair{"function f(min : *, max : min::type) min::type { -> min }\nfunction CLI(request : dval) { f(1, \"x\") }\n", "no overload f"},
|
||||
std::pair{"function CLI(request : dval) { gen_noise(s32(0), s32(1), u64(1), u64(2)) }\n", "no overload __gen_noise"},
|
||||
std::pair{"function f(min : s32, max : min::type) s32 { -> min }\n", "earlier any parameter"},
|
||||
std::pair{"function f(min : any, max : later::type) min::type { -> min }\n", "unknown or forward parameter"},
|
||||
std::pair{"function removed(value : any) value::type { -> value }\n", "unknown type 'any'"},
|
||||
std::pair{"function removed(value : any) {}\n", "unknown type 'any'"},
|
||||
std::pair{"function invalid() * { -> 1 }\n", "unknown type '*'"},
|
||||
std::pair{"function CLI(request : dval) { var invalid : * = 1 }\n", "unknown type '*'"},
|
||||
std::pair{"function invalid(value : as *) {}\n", "requires a concrete named type constructor"},
|
||||
std::pair{"function f(min : s32, max : min::type) s32 { -> min }\n", "earlier * parameter"},
|
||||
std::pair{"function f(min : *, max : later::type) min::type { -> min }\n", "unknown or forward parameter"},
|
||||
std::pair{"function f(value : s32) type(value) { -> value }\n", "type(value) was removed"},
|
||||
std::pair{"function CLI(request : dval) { print(s32(1)::size) }\n", "value::size requires a struct"},
|
||||
std::pair{"function CLI(request : dval) { print(s32(1)::items) }\n", "value::items requires a struct"},
|
||||
@@ -287,7 +292,7 @@ int main()
|
||||
std::pair{"function RENDER(value : s32 = 1) {}\n", "Bearer handlers cannot use default parameters"},
|
||||
std::pair{"function wrong(value : s32 = 1.5) {}\nfunction CLI(request : dval) {}\n", "default parameter literal must have type s32"},
|
||||
std::pair{"function wrong(value : s32 = {}) {}\nfunction CLI(request : dval) {}\n", "default parameter literal must have type s32"},
|
||||
std::pair{"function generic(value : any = 1) value::type { -> value }\nfunction CLI(request : dval) {}\n", "generic functions cannot use default parameters"},
|
||||
std::pair{"function generic(value : * = 1) value::type { -> value }\nfunction CLI(request : dval) {}\n", "generic functions cannot use default parameters"},
|
||||
std::pair{"function values(...value : s32 = 1) {}\nfunction CLI(request : dval) {}\n", "variadic parameter cannot have a default value"},
|
||||
std::pair{"function CLI(request : dval) { var value := function(input : s32 = 1) s32 { -> input } }\n", "anonymous functions cannot use default parameters"},
|
||||
std::pair{"function CLI(request : dval) { var value : function(input : s32 = 1) s32 = function(input : s32) s32 { -> input } }\n", "function types cannot use default parameters"},
|
||||
@@ -537,7 +542,7 @@ int main()
|
||||
const std::string component_render_result_bytes(component_render_result.wasm.begin(), component_render_result.wasm.end());
|
||||
assert(component_render_result_bytes.find("bearer_dv_component_render") != std::string::npos);
|
||||
const auto generic_before_dval = capy::compile_bearer_unit(
|
||||
"function choose(value : any) string { -> \"generic\" }\nfunction choose(value : as dval) string { -> \"dval\" }\nfunction CLI(request : dval) { print(choose(1)) }\n", options);
|
||||
"function choose(value : *) string { -> \"generic\" }\nfunction choose(value : as dval) string { -> \"dval\" }\nfunction CLI(request : dval) { print(choose(1)) }\n", options);
|
||||
const std::string generic_before_dval_bytes(generic_before_dval.wasm.begin(), generic_before_dval.wasm.end());
|
||||
assert(generic_before_dval_bytes.find("bearer_dv_s32") == std::string::npos);
|
||||
for (const char* source : {
|
||||
@@ -550,15 +555,15 @@ int main()
|
||||
try { capy::compile_bearer_unit("function CLI(request : dval) { if var wrong : bool = 1 {} }\n", options); assert(false); }
|
||||
catch (const capy::Error& error) { assert(error.message.find("expected bool, found s64") != std::string::npos); }
|
||||
|
||||
constexpr std::string_view generic_source = "function identity(value : any) value::type { -> value }\n"
|
||||
"function choose(value : any) value::type { -> value }\n"
|
||||
constexpr std::string_view generic_source = "function identity(value : *) value::type { -> value }\n"
|
||||
"function choose(value : *) value::type { -> value }\n"
|
||||
"function choose(value : s32) value::type { -> value + 1 }\n"
|
||||
"function countdown(value : any) value::type { if value == 0 { return value }; return countdown(value - 1) }\n"
|
||||
"function countdown(value : *) value::type { if value == 0 { return value }; return countdown(value - 1) }\n"
|
||||
"function CLI(request : dval) { print(identity(7), choose(4), countdown(3), identity([clone(\"first\"), clone(\"x\")])[1], bool(2)) }\n";
|
||||
const auto generic = capy::compile_bearer_unit(generic_source, options);
|
||||
assert(capy::wasm::validate_bearer_unit(generic.wasm, {.bearer_abi_version = "11"}).valid);
|
||||
const auto generic_method = capy::compile_bearer_unit(
|
||||
"function same(value : any) value::type { -> value }\nfunction CLI(request : dval) { print((7).same()) }\n", options);
|
||||
"function same(value : *) value::type { -> value }\nfunction CLI(request : dval) { print((7).same()) }\n", options);
|
||||
assert(capy::wasm::validate_bearer_unit(generic_method.wasm, {.bearer_abi_version = "11"}).valid);
|
||||
assert(generic_method.source_map.find("F\t1\tnative-test.capy\n") != std::string::npos);
|
||||
const auto converted_parameters = capy::compile_bearer_unit(
|
||||
@@ -633,8 +638,8 @@ int main()
|
||||
assert(module_exports.source_map.find("F\t1\tnative-test.capy\n") != std::string::npos);
|
||||
assert(capy::wasm::validate_bearer_unit(module_exports.wasm, {.bearer_abi_version = "11"}).valid);
|
||||
const auto generic_exports = capy::compile_bearer_unit(
|
||||
"#exports same\nfunction same(first : any, second : first::type) first::type { -> second }\n", options);
|
||||
assert(generic_exports.function_exports == std::vector<std::string>({"capy function same(any,$0::type):$0::type"}));
|
||||
"#exports same\nfunction same(first : *, second : first::type) first::type { -> second }\n", options);
|
||||
assert(generic_exports.function_exports == std::vector<std::string>({"capy function same(*,$0::type):$0::type"}));
|
||||
const auto type_exports = capy::compile_bearer_unit(
|
||||
"#exports echo, MyType, Alias\nstruct MyType { value : s32 }\ntype Alias = MyType\nfunction echo(value : dval) dval { -> value }\nfunction MyType(value : dval) MyType { -> MyType(1) }\n", options);
|
||||
assert(type_exports.custom_exports == std::vector<std::string>({"echo"}));
|
||||
@@ -664,7 +669,7 @@ int main()
|
||||
assert(module_call.source_map.find("F\t2\tcapy://stdlib.capy\n") != std::string::npos);
|
||||
const auto module_passthrough = capy::compile_bearer_unit(
|
||||
"function pass(value : module) module { -> value }\n"
|
||||
"function identity(value : any) value::type { -> value }\n"
|
||||
"function identity(value : *) value::type { -> value }\n"
|
||||
"function CLI(request : dval) { var loaded : module = unit_load(\"child.capy\"); var returned : module = pass(loaded); identity(returned).call(\"invoke\") }\n", options);
|
||||
assert(capy::wasm::validate_bearer_unit(module_passthrough.wasm, {.bearer_abi_version = "11"}).valid);
|
||||
capy::CompileOptions import_options = options;
|
||||
@@ -689,7 +694,7 @@ int main()
|
||||
std::pair{"function bad(value : as [s32]) {}\n", "requires a concrete named type constructor"},
|
||||
std::pair{"function CLI(request : dval) { var callback : function(value : as s64) s64 = function(value : s64) s64 { -> value } }\n", "only variadic function-type parameters may request conversion"},
|
||||
std::pair{"function CLI(request : dval) { var value := 1 as s64 }\n", "call the target type constructor instead"},
|
||||
std::pair{"struct Point { x : s32 }\nfunction string(value : any) string { -> value + \"!\" }\nfunction show(value : as string) {}\nfunction CLI(request : dval) { show(Point(1)) }\n", "string operators require string operands"},
|
||||
std::pair{"struct Point { x : s32 }\nfunction string(value : *) string { -> value + \"!\" }\nfunction show(value : as string) {}\nfunction CLI(request : dval) { show(Point(1)) }\n", "string operators require string operands"},
|
||||
std::pair{"function s32(value : string) string { -> value }\nfunction CLI(request : dval) {}\n", "constructor 's32' must return s32"},
|
||||
std::pair{"struct Point { x : s32 }\nfunction Point(x : s32) Point { -> Point(x) }\nfunction CLI(request : dval) {}\n", "duplicates the generated Point field constructor"},
|
||||
std::pair{"function CLI(request : dval) { var loaded : module = unit_load(\"x\"); var values := [loaded] }\n", "module is opaque and cannot be stored in array layouts"},
|
||||
@@ -924,7 +929,7 @@ int main()
|
||||
std::pair{"function sqlite_connect(path : string) u64 { -> u64(0) }\nfunction CLI(request : dval) {}\n", "reserved by the Capy standard library"},
|
||||
std::pair{"function CLI(request : dval) { var callback : function(__bearer_value : s32) s32 = function(__bearer_value : s32) s32 { -> __bearer_value } }\n", "__bearer_* names are reserved for the Capy standard library"},
|
||||
std::pair{"function CLI(request : dval) { for value, __bearer_key := dval({}) { value } }\n", "__bearer_* names are reserved for the Capy standard library"},
|
||||
std::pair{"function duplicate(value : any) value::type { -> value }\nfunction duplicate(value : any) value::type { -> value }\nfunction CLI(request : dval) {}\n", "duplicate overload duplicate(any)"},
|
||||
std::pair{"function duplicate(value : *) value::type { -> value }\nfunction duplicate(value : *) value::type { -> value }\nfunction CLI(request : dval) {}\n", "duplicate overload duplicate(*)"},
|
||||
})
|
||||
{
|
||||
try
|
||||
@@ -961,8 +966,8 @@ int main()
|
||||
catch (const capy::Error& error) { assert(error.message.find(expected) != std::string::npos); }
|
||||
}
|
||||
for (const auto source : {
|
||||
"function square(value : any) value::type { -> value * value }\nfunction CLI(request : dval) { square(clone(\"x\")) }\n",
|
||||
"function choose(a : any, b : s32) a::type { -> a }\nfunction choose(a : s32, b : any) b::type { -> b }\nfunction CLI(request : dval) { choose(1, 1) }\n",
|
||||
"function square(value : *) value::type { -> value * value }\nfunction CLI(request : dval) { square(clone(\"x\")) }\n",
|
||||
"function choose(a : *, b : s32) a::type { -> a }\nfunction choose(a : s32, b : *) b::type { -> b }\nfunction CLI(request : dval) { choose(1, 1) }\n",
|
||||
"function incomplete(value : bool) s32 { if value { return 1 } }\nfunction CLI(request : dval) { print(incomplete(false)) }\n",
|
||||
"function CLI(request : dval) { print(9223372036854775808) }\n",
|
||||
"function CLI(request : dval) { print(-9223372036854775809) }\n",
|
||||
|
||||
@@ -210,14 +210,16 @@ int main(int argc, char** argv)
|
||||
assert(import->path == "child.capy" && import->alias == "child");
|
||||
}
|
||||
{
|
||||
Program p = parse("function value(min : any, max : min::type) min::type { -> min }\n", "dependent.capy");
|
||||
Program p = parse("function value(min : *, max : min::type) min::type { -> min }\n", "dependent.capy");
|
||||
auto* function = static_cast<Function*>(p.items[0]);
|
||||
assert(function->parameters[0].type_expr->kind == ExprKind::Name);
|
||||
assert(static_cast<Name*>(function->parameters[0].type_expr)->value == "*");
|
||||
assert(type_name(*function->parameters[1].type_expr) == "min::type" && type_name(*function->return_type) == "min::type");
|
||||
auto* parameter_type = static_cast<ScopeLookup*>(function->parameters[1].type_expr);
|
||||
assert(static_cast<Name*>(parameter_type->value)->value == "min" && parameter_type->member == "type");
|
||||
bool rejected = false;
|
||||
try {
|
||||
Program removed = parse("function value(min : any, max : type(min)) type(min) { -> min }\n", "removed.capy");
|
||||
Program removed = parse("function value(min : *, max : type(min)) type(min) { -> min }\n", "removed.capy");
|
||||
type_name(*static_cast<Function*>(removed.items[0])->parameters[1].type_expr);
|
||||
}
|
||||
catch (const Error&) { rejected = true; }
|
||||
@@ -269,7 +271,7 @@ int main(int argc, char** argv)
|
||||
expect_error("function CLI(request : dval) { for value in [1] {} }\n", "old loop syntax is not supported. Use ':=' after the loop bindings");
|
||||
expect_error("function CLI(request : dval) { for value, value := [1] {} }\n", "loop bindings must have different names");
|
||||
expect_error("trace function bad() string {}\n", "trace modifier applies only to host function declarations");
|
||||
expect_error("function bad(value : any, value : any) value::type { value }\n", "function parameter 'value' is already declared");
|
||||
expect_error("function bad(value : *, value : *) value::type { value }\n", "function parameter 'value' is already declared");
|
||||
try
|
||||
{
|
||||
parse("\"broken", "bad.capy");
|
||||
@@ -313,7 +315,7 @@ int main(int argc, char** argv)
|
||||
expect_error("function CLI(request : dval) { #exports first }\n", "#exports is a top-level directive");
|
||||
expect_error("#import child.capy as child\n", "#import requires a string path");
|
||||
expect_error("function CLI(request : dval) { #import \"child.capy\" as child }\n", "#import is a top-level directive");
|
||||
expect_error("function meta(x : any) { #compile { emit(x) } }\n", "#compile compile-time metaprogramming is deferred beyond Capy phase 3");
|
||||
expect_error("function meta(x : *) { #compile { emit(x) } }\n", "#compile compile-time metaprogramming is deferred beyond Capy phase 3");
|
||||
expect_error("#wat", "unknown compiler directive #wat");
|
||||
expect_error("@", "unexpected character '@'");
|
||||
expect_error("1s32", "numeric suffixes were removed");
|
||||
@@ -367,6 +369,12 @@ int main(int argc, char** argv)
|
||||
const std::string expected = "function f(n : s32) s32\n{\n\tvar a := -1;\n\tvar b := n * -2;\n\tif !(a < b)\n\t{\n\t\treturn -a\n\t}\n\t;\n\tfor i := 0..n\n\t{\n\t\ta = a + i\n\t}\n\t;\n\t-> a - b\n}\n";
|
||||
assert(format_source(source) == expected);
|
||||
assert(format_source(expected) == expected);
|
||||
const std::string generic = "function same(first:*,second:first::type) first::type { -> first }\nfunction identity(value:*) value::type { -> value }\n";
|
||||
const std::string generic_formatted = format_source(generic);
|
||||
assert(generic_formatted.find("first : *, second : first::type") != std::string::npos);
|
||||
assert(generic_formatted.find("value : *) value::type") != std::string::npos);
|
||||
assert(format_source(generic_formatted) == generic_formatted);
|
||||
assert(parse(generic_formatted).items.size() == 2);
|
||||
const std::string annotations = "struct Pair { x : s32\ny : s32 }\nfunction f(n : as s32) { var x : dval = {key: -1}\nprint(key: x) }\n";
|
||||
const std::string formatted = format_source(annotations);
|
||||
assert(formatted.find("x : s32") != std::string::npos);
|
||||
|
||||
@@ -3,6 +3,10 @@ const assert = require('node:assert/strict');
|
||||
const fs = require('node:fs');
|
||||
const path = require('node:path');
|
||||
const Prism = require('../site/assets/highlight.js');
|
||||
const vm = require('node:vm');
|
||||
if (process.argv.includes('--source')) {
|
||||
vm.runInNewContext(fs.readFileSync(path.join(__dirname, 'site-highlighter/capy.js'), 'utf8'), { Prism });
|
||||
}
|
||||
|
||||
function text(html) {
|
||||
return html.replace(/<[^>]*>/g, '').replace(/</g, '<').replace(/>/g, '>').replace(/"/g, '"').replace(/&/g, '&');
|
||||
@@ -18,6 +22,16 @@ function check(source, language, tokens = []) {
|
||||
check('#import "/lib/auth.capy" as auth\n#exports current_user\nfunction current_user(input : dval) dval { -> {id: 7, name: "Ada"} }', 'capy', ['directive', 'keyword', 'class-name', 'property', 'function']);
|
||||
check('function COMPONENT: CARD(props : dval) { var title := props.title?; print(title) }', 'capy', ['handler-name', 'operator']);
|
||||
check('function label(name : as string, request : capture dval) string { -> name }', 'capy', ['keyword', 'class-name']);
|
||||
for (const source of ['function same(first : *, second : first::type) first::type', 'function same(first:*) first::type']) {
|
||||
check(source, 'capy', ['generic-type', 'class-name']);
|
||||
assert.match(Prism.highlight(source, Prism.languages.capy, 'capy'), /class="token generic-type class-name">\*<\/span>/);
|
||||
}
|
||||
for (const source of ['var product := left * right', 'var product := left*right', 'print({product: left * right})']) {
|
||||
const html = Prism.highlight(source, Prism.languages.capy, 'capy');
|
||||
assert.match(html, /class="token operator">\*<\/span>/);
|
||||
assert.doesNotMatch(html, /generic-type/);
|
||||
}
|
||||
assert.doesNotMatch(Prism.highlight('var any := 1', Prism.languages.capy, 'capy'), /class-name|generic-type/);
|
||||
check('// "quoted comment"\nprint("escaped \\"quote\\"", 1.5, true, none)', 'capy', ['comment', 'string', 'number', 'boolean']);
|
||||
check('print(<><article class="card"><h1><?= props.title ?></h1><?: props.body ?></article></>)', 'capy', ['html-literal', 'tag', 'capy-field']);
|
||||
check('print(<><section><?= if ready { -> <><b>yes</b></> } else { -> "no" } ?></section></>)', 'capy', ['html-literal', 'keyword']);
|
||||
|
||||
@@ -26,7 +26,8 @@ Prism.languages.ini={comment:{pattern:/(^[ \f\t\v]*)[#;][^\n\r]*/m,lookbehind:!0
|
||||
directive: { pattern: /#(?:callsite|compile|exports|import)\b/, alias: 'keyword' },
|
||||
'handler-name': { pattern: /(\bfunction\s+)[A-Za-z_]\w*(?:\s*:\s*[A-Za-z_]\w*)?(?=\s*\()/, lookbehind: true, alias: 'function' },
|
||||
keyword: /\b(?:break|continue|else|for|function|host|if|return|struct|trace|type|var|while|as|capture|export)\b/,
|
||||
'class-name': /\b(?:any|bool|dval|f32|f64|module|s8|s16|s32|s64|u8|u16|u32|u64|string|void)\b/,
|
||||
'generic-type': { pattern: /(:\s*)\*(?=\s*[,)=])/, lookbehind: true, alias: 'class-name' },
|
||||
'class-name': /\b(?:bool|dval|f32|f64|module|s8|s16|s32|s64|u8|u16|u32|u64|string|void)\b/,
|
||||
boolean: /\b(?:true|false)\b/,
|
||||
constant: /\bnone\b/,
|
||||
function: /\b[A-Za-z_]\w*(?=\s*\()/,
|
||||
|
||||
@@ -1170,7 +1170,7 @@ function COMPONENT(props : dval)
|
||||
{
|
||||
found = true
|
||||
}
|
||||
if consider(tokens, "/doc/guide/values-and-types/", "3. Types", "Learn Capy", "3. Types\nEvery Capy value has a type. The compiler checks types before the program runs. It usually infers the type of a local value.\n\n## Integers\n\nAn integer literal has type `s64` when no other type is stated:\n\n```capy\nfunction RENDER()\n{\n var answer := 42\n print(answer, \"\\n\")\n}\n\n```\n\n**Output**\n\n```text\n42\n\n```\n\nState the type on the local, or construct the value explicitly:\n\n```capy\nfunction RENDER()\n{\n var signed : s64 = 8\n var inferred_signed := s64(9)\n var unsigned : u64 = 10\n var inferred_unsigned := u64(11)\n print(signed, \" \", inferred_signed, \" \", unsigned, \" \", inferred_unsigned, \"\\n\")\n}\n\n```\n\n\nBoth forms produce the stated integer type. `var signed : s64 = s64(8)` also compiles, but the constructor repeats the annotation.\n\nParameters, function results, assignments, typed arrays, struct fields, and the other operand in an expression can also state the integer type. Thus, a function that accepts `u64` can receive the plain literal `8`. An unconstrained literal remains `s64`.\n\nArithmetic requires operands of the same type. Use a constructor when the surrounding code does not state the required type.\n\n## Booleans and floating-point numbers\n\nA `bool` is either `true` or `false`. Conditions require a boolean value.\n\n```capy\nfunction RENDER()\n{\n var enabled := true\n var ratio := 2.5\n print(enabled, \" \", ratio, \"\\n\")\n}\n\n```\n\n\nA decimal point or exponent makes an `f64` literal.\n\n## Strings\n\nA `string` stores bytes:\n\n```capy\nfunction RENDER()\n{\n var name := \"Ada\"\n var empty := \"\"\n print(name, empty, \"\\n\")\n}\n\n```\n\n\nAn empty string is still a string value. It is not missing data.\n\n## Arrays and structs\n\nAn array contains values of one type:\n\n```capy\nfunction RENDER()\n{\n var names := [\"Ada\", \"Grace\"]\n print(names[0], \"\\n\")\n}\n\n```\n\n\nA struct gives names to fixed fields:\n\n```capy\nstruct Point\n{\n x : s32\n y : s32\n}\n\nfunction RENDER()\n{\n var point := Point(3, 4)\n print(point.x, \" \", point.y, \"\\n\")\n}\n\n```\n\n\n## Copy or share\n\nNumbers and booleans are copied: after `var b := a`, changing `b` leaves `a` alone. Strings are values too. A string never changes in place, so it makes no difference whether two names share one.\n\nArrays, structs, and dvals are objects. `var b := a` makes `b` a second name for the same object, and so do parameters, return values, closure captures, and member reads. A change made through one name shows through all of them. When you need a separate copy, `clone(value)` makes one.\n\nA variable can be pointed at another object with `=`. A parameter cannot.\n\nThe collections chapter covers arrays and structs in detail, the dynamic values chapter covers `dval`.\n\n## Numeric functions\n\nUse the `math` functions for floating-point calculations and numeric bounds. Use the `bits` functions for integer masks, shifts, rotations, counts, and bit reinterpretation.\n\nSee the `math` function reference for floating-point operations and predicates. See the `bits` function reference for integer bit operations and floating-point bit reinterpretation.\n\n## Dynamic values and none\n\nA `dval` holds data whose shape is known only at run time. The `none` value represents missing dynamic data:\n\n```capy\nfunction RENDER()\n{\n var profile := { name: \"Ada\" }\n var missing := none\n print(profile.name, \" \", missing?, \"\\n\")\n}\n\n```\n\n\n`none` is different from `\"\"`, `false`, an empty map, and an empty list. A `dval` is also an object that variables refer to, never a copy. The dynamic-values chapter explains mutation, safe reads, and conversions.\n\n## Type aliases and static type names\n\nA type alias gives another name to a type. It does not create a distinct type at runtime.\n\nUse `expression::type_name` to get the resolved static type of an expression. Capy evaluates the expression once.\n\n```capy\ntype Count = s64\n\nfunction RENDER()\n{\n var total : Count = 12\n var labels := [\"new\", \"done\"]\n print(total::type_name, \" \", labels::type_name, \"\\n\")\n}\n\n```\n\n**Output**\n\n```text\ns64 [string]\n\n```\n\n\nAn alias reports its target type. Arrays use `[item_type]`. Structs use their declared name. Function values use their complete function type.\n\nA `dval` expression reports `dval`, regardless of its current contents. Use `get_type_name(value)` to inspect the value stored inside a `dval`.\n\n## Struct field inspection\n\nStruct values have two additional reflection expressions:\n\n| Expression | Result | Meaning |\n| --- | --- | --- |\n| `value::size` | `s64` | The number of declared fields. This is not a byte size. |\n| `value::items` | `dval` | A new map of the current field values, keyed by field name. |\n\nEach `items` entry contains `value` and `type_name`. Use `fields.name.value` for a fixed field. Use `fields[key][\"value\"]` for a dynamic field namLine truncated
|
||||
if consider(tokens, "/doc/guide/values-and-types/", "3. Types", "Learn Capy", "3. Types\nEvery Capy value has a type. The compiler checks types before the program runs. It usually infers the type of a local value.\n\n## Integers\n\nAn integer literal has type `s64` when no other type is stated:\n\n```capy\nfunction RENDER()\n{\n var answer := 42\n print(answer, \"\\n\")\n}\n\n```\n\n**Output**\n\n```text\n42\n\n```\n\nState the type on the local, or construct the value explicitly:\n\n```capy\nfunction RENDER()\n{\n var signed : s64 = 8\n var inferred_signed := s64(9)\n var unsigned : u64 = 10\n var inferred_unsigned := u64(11)\n print(signed, \" \", inferred_signed, \" \", unsigned, \" \", inferred_unsigned, \"\\n\")\n}\n\n```\n\n\nBoth forms produce the stated integer type. `var signed : s64 = s64(8)` also compiles, but the constructor repeats the annotation.\n\nParameters, function results, assignments, typed arrays, struct fields, and the other operand in an expression can also state the integer type. Thus, a function that accepts `u64` can receive the plain literal `8`. An unconstrained literal remains `s64`.\n\nArithmetic requires operands of the same type. Use a constructor when the surrounding code does not state the required type.\n\n## Booleans and floating-point numbers\n\nA `bool` is either `true` or `false`. Conditions require a boolean value.\n\n```capy\nfunction RENDER()\n{\n var enabled := true\n var ratio := 2.5\n print(enabled, \" \", ratio, \"\\n\")\n}\n\n```\n\n\nA decimal point or exponent makes an `f64` literal.\n\n## Strings\n\nA `string` stores bytes:\n\n```capy\nfunction RENDER()\n{\n var name := \"Ada\"\n var empty := \"\"\n print(name, empty, \"\\n\")\n}\n\n```\n\n\nAn empty string is still a string value. It is not missing data.\n\n## Arrays and structs\n\nAn array contains values of one type:\n\n```capy\nfunction RENDER()\n{\n var names := [\"Ada\", \"Grace\"]\n print(names[0], \"\\n\")\n}\n\n```\n\n\nA struct gives names to fixed fields:\n\n```capy\nstruct Point\n{\n x : s32\n y : s32\n}\n\nfunction RENDER()\n{\n var point := Point(3, 4)\n print(point.x, \" \", point.y, \"\\n\")\n}\n\n```\n\n\n## Copy or share\n\nNumbers and booleans are copied: after `var b := a`, changing `b` leaves `a` alone. Strings are values too. A string never changes in place, so it makes no difference whether two names share one.\n\nArrays, structs, and dvals are objects. `var b := a` makes `b` a second name for the same object, and so do parameters, return values, closure captures, and member reads. A change made through one name shows through all of them. When you need a separate copy, `clone(value)` makes one.\n\nA variable can be pointed at another object with `=`. A parameter cannot.\n\nThe collections chapter covers arrays and structs in detail, the dynamic values chapter covers `dval`.\n\n## Numeric functions\n\nUse the `math` functions for floating-point calculations and numeric bounds. Use the `bits` functions for integer masks, shifts, rotations, counts, and bit reinterpretation.\n\nSee the `math` function reference for floating-point operations and predicates. See the `bits` function reference for integer bit operations and floating-point bit reinterpretation.\n\n## Dynamic values and none\n\nA `dval` holds data whose shape is known only at run time. The `none` value represents missing dynamic data:\n\n```capy\nfunction RENDER()\n{\n var profile := { name: \"Ada\" }\n var missing := none\n print(profile.name, \" \", missing?, \"\\n\")\n}\n\n```\n\n\n`none` is different from `\"\"`, `false`, an empty map, and an empty list. A `dval` is also an object that variables refer to, never a copy. The dynamic-values chapter explains mutation, safe reads, and conversions.\n\n## Type aliases and static type names\n\nA type alias gives another name to a type. It does not create a distinct type at runtime.\n\nUse `expression::type_name` to get the resolved static type of an expression. Capy evaluates the expression once.\n\n```capy\ntype Count = s64\n\nfunction RENDER()\n{\n var total : Count = 12\n var labels := [\"new\", \"done\"]\n print(total::type_name, \" \", labels::type_name, \"\\n\")\n}\n\n```\n\n**Output**\n\n```text\ns64 [string]\n\n```\n\n\nAn alias reports its target type. Arrays use `[item_type]`. Structs use their declared name. Function values use their complete function type.\n\nA `dval` expression reports `dval`, regardless of its current contents. Use `get_type_name(value)` to inspect the value stored inside a `dval`.\n\n## Struct field inspection\n\nStruct values have two additional reflection expressions:\n\n| Expression | Result | Meaning |\n| --- | --- | --- |\n| `value::size` | `s64` | The number of declared fields. This is not a byte size. |\n| `value::items` | `dval` | A new map of the current field values, keyed by field name. |\n\nEach `items` entry contains `value` and `type_name`. Use `fields.name.value` for a fixed field. Use `fields[key][\"value\"]` for a dynamic field namLine truncated
|
||||
{
|
||||
found = true
|
||||
}
|
||||
@@ -1178,7 +1178,7 @@ function COMPONENT(props : dval)
|
||||
{
|
||||
found = true
|
||||
}
|
||||
if consider(tokens, "/doc/guide/functions-and-closures/", "5. Functions", "Learn Capy", "5. Functions\nA function gives a name to a calculation. Parameters describe its input. The declared result type describes its output.\n\n## Define and call a function\n\n```capy\nfunction greet(name : capture string) string\n{\n -> \"Hello, \" + name\n}\n\nfunction RENDER()\n{\n var name := \"Ada\"\n print(greet(), \"\\n\")\n}\n\n```\n\n**Output**\n\n```text\nHello, Ada\n\n```\n\nThe `->` expression supplies the function result. Use `return` when a function must finish early.\n\n## Parameters and defaults\n\nParameters have names and types:\n\n```capy\nfunction label(name : string, suffix : string = \"!\") string\n{\n -> name + suffix\n}\n\nfunction RENDER()\n{\n print(label(\"Capy\"), \"\\n\")\n}\n\n```\n\n\n`label(\"Capy\")` uses the default suffix. Defaults are trailing literals. A direct call can omit them, but a function value keeps the full parameter list.\n\nCapy evaluates arguments once from left to right.\n\n## Capture parameters\n\nA capture parameter uses the caller's variable with the same name when the caller omits its argument. The first example captures `name`.\n\nWrite `name : capture Type` for an exact type match. Write `name : capture as Type` to permit one constructor conversion.\n\nCapture parameters follow all ordinary parameters, including parameters with defaults. The caller can also pass an explicit argument.\n\nA missing caller variable is a compile error. The diagnostic names the function and the capture parameter.\n\nA helper that uses request-dependent functions must declare `request : capture dval`. Each helper in a call chain needs that capture.\n\n```capy\nfunction set_title(title : string, request : capture dval)\n{\n request.page_title = title\n}\n```\n\nHandlers bind `request` implicitly. Exported `(dval) dval` functions also capture `request` implicitly. They need no explicit capture declaration.\n\n## Map entry arguments\n\nAn argument of the form `key: value` is a map entry. Adjacent map entries form one map argument:\n\n```capy\nfunction describe(name : string, options : dval = {}) string\n{\n -> name + \" \" + json_encode(options)\n}\n\nfunction RENDER()\n{\n print(describe(\"list\", page: 2, per_page: 20), \"\\n\")\n print(describe(\"list\",\n {\n page: 2,\n per_page: 20\n }\n ),\n \"\\n\"\n )\n}\n\n```\n\n**Output**\n\n```text\nlist {\"page\": 2.000000, \"per_page\": 20.000000}\nlist {\"page\": 2.000000, \"per_page\": 20.000000}\n\n```\n\n\nBoth calls pass the same map and compile to the same code. Use map entries for options and for the input of a unit call.\n\nA map entry does not name a parameter. `describe(name: \"list\")` passes one map, and the compiler reports that no overload accepts it. A key is an identifier or a string.\n\nAn ordinary argument ends the map. In `find(1, page: 2, true)` the call receives `1`, the map `{page: 2}`, and `true`. Two map parameters in sequence need braces for the second map. Struct constructors take ordinary arguments.\n\n## Overloads\n\nSeveral functions can have the same name when their parameter types differ:\n\n```capy\nfunction describe(value : s32) string\n{\n -> \"integer\"\n}\nfunction describe(value : string) string\n{\n -> \"string\"\n}\n\nfunction RENDER()\n{\n print(describe(42), \" \", describe(\"Ada\"), \"\\n\")\n}\n\n```\n\n\nThe argument types select the overload. A result type never selects one.\n\n## Conversion parameters\n\nA parameter declared with `as` permits one constructor conversion:\n\n```capy\nfunction show(value : as string)\n{\n print(value, \"\\n\")\n}\n\nfunction RENDER()\n{\n show(42)\n}\n\n```\n\n\nThe call behaves as if it passed `string(42)`. Capy does not chain several conversions.\n\n## Function values\n\nA function can be stored and called through a typed value:\n\n```capy\nfunction double(value : s32) s32\n{\n -> value * 2\n}\n\nfunction RENDER()\n{\n var operation : function(value : s32) s32 = double\n var answer := operation(21)\n print(answer, \"\\n\")\n}\n\n```\n\n\nA lambda defines a small function at its point of use:\n\n```capy\nfunction RENDER()\n{\n var add_one := function(value : s32) s32\n {\n -> value + 1\n }\n print(add_one(41), \"\\n\")\n}\n\n```\n\n\nA lambda can read outer variables. A captured number, boolean, or string is copied. A captured array, `dval`, or struct is the same object the outer code holds, so the closure can change its contents and the outer code sees the change. A capture cannot be reassigned.\n\n```capy\nfunction RENDER()\n{\n var offset := 2\n var values := [10]\n var update := function() s64\n {\n values.push(20)\n -> offset + length(values)\n }\n print(update(), \" \", values[1], \"\\n\")\n}\n\n```\n\n\n## Store a callback in a dynamic value\n\nA `dval` can store a named function or a closure for the rest of the request. Read it with its complete function type:\n\n```capy\nfunction add_one(value : s32) s32\n{\n -> value + 1\n}\n\nfunction RENDER()\n{\n vLine truncated
|
||||
if consider(tokens, "/doc/guide/functions-and-closures/", "5. Functions", "Learn Capy", "5. Functions\nA function gives a name to a calculation. Parameters describe its input. The declared result type describes its output.\n\n## Define and call a function\n\n```capy\nfunction greet(name : capture string) string\n{\n -> \"Hello, \" + name\n}\n\nfunction RENDER()\n{\n var name := \"Ada\"\n print(greet(), \"\\n\")\n}\n\n```\n\n**Output**\n\n```text\nHello, Ada\n\n```\n\nThe `->` expression supplies the function result. Use `return` when a function must finish early.\n\n## Parameters and defaults\n\nParameters have names and types:\n\n```capy\nfunction label(name : string, suffix : string = \"!\") string\n{\n -> name + suffix\n}\n\nfunction RENDER()\n{\n print(label(\"Capy\"), \"\\n\")\n}\n\n```\n\n\n`label(\"Capy\")` uses the default suffix. Defaults are trailing literals. A direct call can omit them, but a function value keeps the full parameter list.\n\nCapy evaluates arguments once from left to right.\n\n## Capture parameters\n\nA capture parameter uses the caller's variable with the same name when the caller omits its argument. The first example captures `name`.\n\nWrite `name : capture Type` for an exact type match. Write `name : capture as Type` to permit one constructor conversion.\n\nCapture parameters follow all ordinary parameters, including parameters with defaults. The caller can also pass an explicit argument.\n\nA missing caller variable is a compile error. The diagnostic names the function and the capture parameter.\n\nA helper that uses request-dependent functions must declare `request : capture dval`. Each helper in a call chain needs that capture.\n\n```capy\nfunction set_title(title : string, request : capture dval)\n{\n request.page_title = title\n}\n```\n\nHandlers bind `request` implicitly. Exported `(dval) dval` functions also capture `request` implicitly. They need no explicit capture declaration.\n\n## Map entry arguments\n\nAn argument of the form `key: value` is a map entry. Adjacent map entries form one map argument:\n\n```capy\nfunction describe(name : string, options : dval = {}) string\n{\n -> name + \" \" + json_encode(options)\n}\n\nfunction RENDER()\n{\n print(describe(\"list\", page: 2, per_page: 20), \"\\n\")\n print(describe(\"list\",\n {\n page: 2,\n per_page: 20\n }\n ),\n \"\\n\"\n )\n}\n\n```\n\n**Output**\n\n```text\nlist {\"page\": 2.000000, \"per_page\": 20.000000}\nlist {\"page\": 2.000000, \"per_page\": 20.000000}\n\n```\n\n\nBoth calls pass the same map and compile to the same code. Use map entries for options and for the input of a unit call.\n\nA map entry does not name a parameter. `describe(name: \"list\")` passes one map, and the compiler reports that no overload accepts it. A key is an identifier or a string.\n\nAn ordinary argument ends the map. In `find(1, page: 2, true)` the call receives `1`, the map `{page: 2}`, and `true`. Two map parameters in sequence need braces for the second map. Struct constructors take ordinary arguments.\n\n## Overloads\n\nSeveral functions can have the same name when their parameter types differ:\n\n```capy\nfunction describe(value : s32) string\n{\n -> \"integer\"\n}\nfunction describe(value : string) string\n{\n -> \"string\"\n}\n\nfunction RENDER()\n{\n print(describe(42), \" \", describe(\"Ada\"), \"\\n\")\n}\n\n```\n\n\nThe argument types select the overload. A result type never selects one.\n\n## Conversion parameters\n\nA parameter declared with `as` permits one constructor conversion:\n\n```capy\nfunction show(value : as string)\n{\n print(value, \"\\n\")\n}\n\nfunction RENDER()\n{\n show(42)\n}\n\n```\n\n\nThe call behaves as if it passed `string(42)`. Capy does not chain several conversions.\n\n## Function values\n\nA function can be stored and called through a typed value:\n\n```capy\nfunction double(value : s32) s32\n{\n -> value * 2\n}\n\nfunction RENDER()\n{\n var operation : function(value : s32) s32 = double\n var answer := operation(21)\n print(answer, \"\\n\")\n}\n\n```\n\n\nA lambda defines a small function at its point of use:\n\n```capy\nfunction RENDER()\n{\n var add_one := function(value : s32) s32\n {\n -> value + 1\n }\n print(add_one(41), \"\\n\")\n}\n\n```\n\n\nA lambda can read outer variables. A captured number, boolean, or string is copied. A captured array, `dval`, or struct is the same object the outer code holds, so the closure can change its contents and the outer code sees the change. A capture cannot be reassigned.\n\n```capy\nfunction RENDER()\n{\n var offset := 2\n var values := [10]\n var update := function() s64\n {\n values.push(20)\n -> offset + length(values)\n }\n print(update(), \" \", values[1], \"\\n\")\n}\n\n```\n\n\n## Store a callback in a dynamic value\n\nA `dval` can store a named function or a closure for the rest of the request. Read it with its complete function type:\n\n```capy\nfunction add_one(value : s32) s32\n{\n -> value + 1\n}\n\nfunction RENDER()\n{\n vLine truncated
|
||||
{
|
||||
found = true
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
function COMPONENT(props : dval)
|
||||
{
|
||||
print("<div class=\"doc-detail-layout\"><main class=\"content doc-page doc-detail\"><div class=\"doc-title\"><h2>gen_noise</h2><span class=\"call-boundary host-call\">host call</span></div><div class=\"doc-section signatures\"><h3>Capy</h3><pre>function gen_noise(min : any, max : min::type, index : u64, seed : u64) min::type</pre></div><div class=\"doc-section content\"><h3>Description</h3><p><code>gen_noise()</code> returns deterministic noise for the range values, index, and seed.</p><p>Only <code>u64</code> and <code>f64</code> bounds are supported. Integer bounds are inclusive.</p><p>Float generation uses the existing fixed precision. The function does not accept a precision parameter.</p><p>Use the same inputs to reproduce a value.</p></div><div class=\"doc-section params\"><h3>Parameters</h3><div><p>min : first range value</p></div><div><p>max : second range value</p></div><div><p>index : deterministic input position</p></div><div><p>seed : deterministic input seed</p></div><div></div></div><div class=\"doc-section\"><h3>Return Values</h3><p>A deterministic value with the same type as <code>min</code>.</p></div><div class=\"doc-section example\"><h3>Example</h3><div class=\"example-language capy\"><h4>Capy</h4><pre class=\"example-source\">var integer := gen_noise(u64(1), u64(10), u64(1), u64(2))\nvar floating := gen_noise(0.0, 1.0, u64(1), u64(2))\nprint(integer, " ", floating, "\\n")\n</pre></div></div></main><aside class=\"doc-section see-also\"><h3>See also</h3><a class=\"related-link\" href=\"/doc/api/gen-noise64/\">gen_noise64</a><a class=\"related-link\" href=\"/doc/api/draw-int/\">draw_int</a><a class=\"related-link\" href=\"/doc/api/draw-float/\">draw_float</a><a class=\"related-link\" href=\"/doc/api/random-bytes/\">random_bytes</a></aside></div>")
|
||||
print("<div class=\"doc-detail-layout\"><main class=\"content doc-page doc-detail\"><div class=\"doc-title\"><h2>gen_noise</h2><span class=\"call-boundary host-call\">host call</span></div><div class=\"doc-section signatures\"><h3>Capy</h3><pre>function gen_noise(min : *, max : min::type, index : u64, seed : u64) min::type</pre></div><div class=\"doc-section content\"><h3>Description</h3><p><code>gen_noise()</code> returns deterministic noise for the range values, index, and seed.</p><p>Only <code>u64</code> and <code>f64</code> bounds are supported. Integer bounds are inclusive.</p><p>Float generation uses the existing fixed precision. The function does not accept a precision parameter.</p><p>Use the same inputs to reproduce a value.</p></div><div class=\"doc-section params\"><h3>Parameters</h3><div><p>min : first range value</p></div><div><p>max : second range value</p></div><div><p>index : deterministic input position</p></div><div><p>seed : deterministic input seed</p></div><div></div></div><div class=\"doc-section\"><h3>Return Values</h3><p>A deterministic value with the same type as <code>min</code>.</p></div><div class=\"doc-section example\"><h3>Example</h3><div class=\"example-language capy\"><h4>Capy</h4><pre class=\"example-source\">var integer := gen_noise(u64(1), u64(10), u64(1), u64(2))\nvar floating := gen_noise(0.0, 1.0, u64(1), u64(2))\nprint(integer, " ", floating, "\\n")\n</pre></div></div></main><aside class=\"doc-section see-also\"><h3>See also</h3><a class=\"related-link\" href=\"/doc/api/gen-noise64/\">gen_noise64</a><a class=\"related-link\" href=\"/doc/api/draw-int/\">draw_int</a><a class=\"related-link\" href=\"/doc/api/draw-float/\">draw_float</a><a class=\"related-link\" href=\"/doc/api/random-bytes/\">random_bytes</a></aside></div>")
|
||||
}
|
||||
@@ -3,6 +3,6 @@ function COMPONENT(props : dval)
|
||||
print("<div class=\"doc-detail-layout\"><main class=\"content doc-page doc-detail\"><div class=\"doc-title\"><h2>5. Functions</h2></div><div class=\"doc-section content\"><p>A function gives a name to a calculation. Parameters describe its input. The declared result type describes its output.</p><h2>Define and call a function</h2><pre><code class=\"language-capy\">function greet(name : capture string) string\n{\n -> "Hello, " + name\n}\n\nfunction RENDER()\n{\n var name := "Ada"\n print(greet(), "\\n")\n}\n</code></pre><p><strong>Output</strong></p><pre><code class=\"language-text\">Hello, Ada\n</code></pre><p>The <code>-></code> expression supplies the function result. Use <code>return</code> when a function must finish early.</p><h2>Parameters and defaults</h2><p>Parameters have names and types:</p><pre><code class=\"language-capy\">function label(name : string, suffix : string = "!") string\n{\n -> name + suffix\n}\n\nfunction RENDER()\n{\n print(label("Capy"), "\\n")\n}\n</code></pre><p><code>label("Capy")</code> uses the default suffix. Defaults are trailing literals. A direct call can omit them, but a function value keeps the full parameter list.</p><p>Capy evaluates arguments once from left to right.</p><h2>Capture parameters</h2><p>A capture parameter uses the caller's variable with the same name when the caller omits its argument. The first example captures <code>name</code>.</p><p>Write <code>name : capture Type</code> for an exact type match. Write <code>name : capture as Type</code> to permit one constructor conversion.</p><p>Capture parameters follow all ordinary parameters, including parameters with defaults. The caller can also pass an explicit argument.</p><p>A missing caller variable is a compile error. The diagno")
|
||||
print("stic names the function and the capture parameter.</p><p>A helper that uses request-dependent functions must declare <code>request : capture dval</code>. Each helper in a call chain needs that capture.</p><pre><code class=\"language-capy\">function set_title(title : string, request : capture dval)\n{\n request.page_title = title\n}</code></pre><p>Handlers bind <code>request</code> implicitly. Exported <code>(dval) dval</code> functions also capture <code>request</code> implicitly. They need no explicit capture declaration.</p><h2>Map entry arguments</h2><p>An argument of the form <code>key: value</code> is a map entry. Adjacent map entries form one map argument:</p><pre><code class=\"language-capy\">function describe(name : string, options : dval = {}) string\n{\n -> name + " " + json_encode(options)\n}\n\nfunction RENDER()\n{\n print(describe("list", page: 2, per_page: 20), "\\n")\n print(describe("list",\n {\n page: 2,\n per_page: 20\n }\n ),\n "\\n"\n )\n}\n</code></pre><p><strong>Output</strong></p><pre><code class=\"language-text\">list {"page": 2.000000, "per_page": 20.000000}\nlist {"page": 2.000000, "per_page": 20.000000}\n</code></pre><p>Both calls pass the same map and compile to the same code. Use map entries for options and for the input of a unit call.</p><p>A map entry does not name a parameter. <code>describe(name: "list")</code> passes one map, and the compiler reports that no overload accepts it. A key is an identifier or a string.</p><p>An ordinary argument ends the map. In <code>find(1, page: 2, true)</code> the call receives <code>1</code>, the map <code>{page: 2}</code>, and <code>true</code>. Two map parameters in sequence need braces for the second map. Struct construc")
|
||||
print("tors take ordinary arguments.</p><h2>Overloads</h2><p>Several functions can have the same name when their parameter types differ:</p><pre><code class=\"language-capy\">function describe(value : s32) string\n{\n -> "integer"\n}\nfunction describe(value : string) string\n{\n -> "string"\n}\n\nfunction RENDER()\n{\n print(describe(42), " ", describe("Ada"), "\\n")\n}\n</code></pre><p>The argument types select the overload. A result type never selects one.</p><h2>Conversion parameters</h2><p>A parameter declared with <code>as</code> permits one constructor conversion:</p><pre><code class=\"language-capy\">function show(value : as string)\n{\n print(value, "\\n")\n}\n\nfunction RENDER()\n{\n show(42)\n}\n</code></pre><p>The call behaves as if it passed <code>string(42)</code>. Capy does not chain several conversions.</p><h2>Function values</h2><p>A function can be stored and called through a typed value:</p><pre><code class=\"language-capy\">function double(value : s32) s32\n{\n -> value * 2\n}\n\nfunction RENDER()\n{\n var operation : function(value : s32) s32 = double\n var answer := operation(21)\n print(answer, "\\n")\n}\n</code></pre><p>A lambda defines a small function at its point of use:</p><pre><code class=\"language-capy\">function RENDER()\n{\n var add_one := function(value : s32) s32\n {\n -> value + 1\n }\n print(add_one(41), "\\n")\n}\n</code></pre><p>A lambda can read outer variables. A captured number, boolean, or string is copied. A captured array, <code>dval</code>, or struct is the same object the outer code holds, so the closure can change its contents and the outer code sees the change. A capture cannot be reassigned.</p><pre><code class=\"language-capy\">function RENDER()\n{\n var offset := 2\n var values := [10]\n var ")
|
||||
print("update := function() s64\n {\n values.push(20)\n -> offset + length(values)\n }\n print(update(), " ", values[1], "\\n")\n}\n</code></pre><h2>Store a callback in a dynamic value</h2><p>A <code>dval</code> can store a named function or a closure for the rest of the request. Read it with its complete function type:</p><pre><code class=\"language-capy\">function add_one(value : s32) s32\n{\n -> value + 1\n}\n\nfunction RENDER()\n{\n var step := s32(2)\n var callbacks := {\n named: add_one,\n captured: function(value : s32) s32\n {\n -> value + step\n }\n }\n var named : function(value : s32) s32 = callbacks.named\n var captured : function(value : s32) s32 = callbacks.captured\n print(named(1), " ", captured(1), "\\n")\n}\n</code></pre><p><strong>Output</strong></p><pre><code class=\"language-text\">2 3\n</code></pre><p>The function type must match exactly. A mismatch traps. A callable does not cross a public boundary. BRRB, JSON, YAML, and XML replace it with <code>none</code>. Maps keep keys. Lists keep indexes.</p><h2>Generic and variadic functions</h2><p>An <code>any</code> parameter creates a compile-time generic function. Use it when the same operation is valid for several concrete types.</p><p>A variadic parameter collects values into a typed array:</p><pre><code class=\"language-capy\">function print_all(...values : as string)\n{\n for value := values\n {\n print(value)\n }\n}\n\nfunction RENDER()\n{\n print_all("one", " ", "two", "\\n")\n}\n</code></pre><p>Use <code>...items</code> to spread an array into a variadic call.</p></div><nav class=\"guide-navigation\" aria-label=\"Capy guide navigation\"><div class=\"guide-previous\">Previous: <a href=\"/doc/guide/expressions-and-control-flow/\">4. Expressions and control flow</a")
|
||||
print("></div><div class=\"guide-index\"><a href=\"/doc/\">Guide index</a></div><div class=\"guide-next\">Next: <a href=\"/doc/guide/strings-and-markup/\">6. Strings and HTML</a></div></nav></main><aside class=\"doc-section see-also\"><h3>See also</h3><a class=\"related-link\" href=\"/doc/guide/install-and-first-program/\">1. Getting started</a><a class=\"related-link\" href=\"/doc/guide/source-structure-and-syntax/\">2. Basic syntax</a><a class=\"related-link\" href=\"/doc/guide/values-and-types/\">3. Types</a><a class=\"related-link\" href=\"/doc/guide/expressions-and-control-flow/\">4. Expressions and control flow</a><a class=\"related-link\" href=\"/doc/guide/strings-and-markup/\">6. Strings and HTML</a><a class=\"related-link\" href=\"/doc/guide/collections-and-records/\">7. Arrays and structs</a><a class=\"related-link\" href=\"/doc/guide/dynamic-values/\">8. Dynamic values</a><a class=\"related-link\" href=\"/doc/guide/web-handlers-and-requests/\">9. Handling a web request</a><a class=\"related-link\" href=\"/doc/guide/units-components-and-exports/\">10. Units and components</a><a class=\"related-link\" href=\"/doc/guide/tasks-and-commands/\">11. Tasks and commands</a><a class=\"related-link\" href=\"/doc/guide/services/\">12. Services</a><a class=\"related-link\" href=\"/doc/guide/errors-testing-and-style/\">13. Errors and testing</a><a class=\"related-link\" href=\"/doc/guide/coming-from-react/\">14. Coming from React</a><a class=\"related-link\" href=\"/doc/api/print/\">print</a></aside></div>")
|
||||
print("update := function() s64\n {\n values.push(20)\n -> offset + length(values)\n }\n print(update(), " ", values[1], "\\n")\n}\n</code></pre><h2>Store a callback in a dynamic value</h2><p>A <code>dval</code> can store a named function or a closure for the rest of the request. Read it with its complete function type:</p><pre><code class=\"language-capy\">function add_one(value : s32) s32\n{\n -> value + 1\n}\n\nfunction RENDER()\n{\n var step := s32(2)\n var callbacks := {\n named: add_one,\n captured: function(value : s32) s32\n {\n -> value + step\n }\n }\n var named : function(value : s32) s32 = callbacks.named\n var captured : function(value : s32) s32 = callbacks.captured\n print(named(1), " ", captured(1), "\\n")\n}\n</code></pre><p><strong>Output</strong></p><pre><code class=\"language-text\">2 3\n</code></pre><p>The function type must match exactly. A mismatch traps. A callable does not cross a public boundary. BRRB, JSON, YAML, and XML replace it with <code>none</code>. Maps keep keys. Lists keep indexes.</p><h2>Generic and variadic functions</h2><p>A <code>*</code> parameter creates a compile-time generic function. Use it when the same operation is valid for several concrete types.</p><p>A variadic parameter collects values into a typed array:</p><pre><code class=\"language-capy\">function print_all(...values : as string)\n{\n for value := values\n {\n print(value)\n }\n}\n\nfunction RENDER()\n{\n print_all("one", " ", "two", "\\n")\n}\n</code></pre><p>Use <code>...items</code> to spread an array into a variadic call.</p></div><nav class=\"guide-navigation\" aria-label=\"Capy guide navigation\"><div class=\"guide-previous\">Previous: <a href=\"/doc/guide/expressions-and-control-flow/\">4. Expressions and control flow</a></")
|
||||
print("div><div class=\"guide-index\"><a href=\"/doc/\">Guide index</a></div><div class=\"guide-next\">Next: <a href=\"/doc/guide/strings-and-markup/\">6. Strings and HTML</a></div></nav></main><aside class=\"doc-section see-also\"><h3>See also</h3><a class=\"related-link\" href=\"/doc/guide/install-and-first-program/\">1. Getting started</a><a class=\"related-link\" href=\"/doc/guide/source-structure-and-syntax/\">2. Basic syntax</a><a class=\"related-link\" href=\"/doc/guide/values-and-types/\">3. Types</a><a class=\"related-link\" href=\"/doc/guide/expressions-and-control-flow/\">4. Expressions and control flow</a><a class=\"related-link\" href=\"/doc/guide/strings-and-markup/\">6. Strings and HTML</a><a class=\"related-link\" href=\"/doc/guide/collections-and-records/\">7. Arrays and structs</a><a class=\"related-link\" href=\"/doc/guide/dynamic-values/\">8. Dynamic values</a><a class=\"related-link\" href=\"/doc/guide/web-handlers-and-requests/\">9. Handling a web request</a><a class=\"related-link\" href=\"/doc/guide/units-components-and-exports/\">10. Units and components</a><a class=\"related-link\" href=\"/doc/guide/tasks-and-commands/\">11. Tasks and commands</a><a class=\"related-link\" href=\"/doc/guide/services/\">12. Services</a><a class=\"related-link\" href=\"/doc/guide/errors-testing-and-style/\">13. Errors and testing</a><a class=\"related-link\" href=\"/doc/guide/coming-from-react/\">14. Coming from React</a><a class=\"related-link\" href=\"/doc/api/print/\">print</a></aside></div>")
|
||||
}
|
||||
@@ -3,7 +3,7 @@ function COMPONENT(props : dval)
|
||||
print("<div class=\"doc-detail-layout\"><main class=\"content doc-page doc-detail\"><div class=\"doc-title\"><h2>3. Types</h2></div><div class=\"doc-section content\"><p>Every Capy value has a type. The compiler checks types before the program runs. It usually infers the type of a local value.</p><h2>Integers</h2><p>An integer literal has type <code>s64</code> when no other type is stated:</p><pre><code class=\"language-capy\">function RENDER()\n{\n var answer := 42\n print(answer, "\\n")\n}\n</code></pre><p><strong>Output</strong></p><pre><code class=\"language-text\">42\n</code></pre><p>State the type on the local, or construct the value explicitly:</p><pre><code class=\"language-capy\">function RENDER()\n{\n var signed : s64 = 8\n var inferred_signed := s64(9)\n var unsigned : u64 = 10\n var inferred_unsigned := u64(11)\n print(signed, " ", inferred_signed, " ", unsigned, " ", inferred_unsigned, "\\n")\n}\n</code></pre><p>Both forms produce the stated integer type. <code>var signed : s64 = s64(8)</code> also compiles, but the constructor repeats the annotation.</p><p>Parameters, function results, assignments, typed arrays, struct fields, and the other operand in an expression can also state the integer type. Thus, a function that accepts <code>u64</code> can receive the plain literal <code>8</code>. An unconstrained literal remains <code>s64</code>.</p><p>Arithmetic requires operands of the same type. Use a constructor when the surrounding code does not state the required type.</p><h2>Booleans and floating-point numbers</h2><p>A <code>bool</code> is either <code>true</code> or <code>false</code>. Conditions require a boolean value.</p><pre><code class=\"language-capy\">function RENDER()\n{\n var enabled := true\n var ratio := 2.5\n print(enabled, " "")
|
||||
print(", ratio, "\\n")\n}\n</code></pre><p>A decimal point or exponent makes an <code>f64</code> literal.</p><h2>Strings</h2><p>A <code>string</code> stores bytes:</p><pre><code class=\"language-capy\">function RENDER()\n{\n var name := "Ada"\n var empty := ""\n print(name, empty, "\\n")\n}\n</code></pre><p>An empty string is still a string value. It is not missing data.</p><h2>Arrays and structs</h2><p>An array contains values of one type:</p><pre><code class=\"language-capy\">function RENDER()\n{\n var names := ["Ada", "Grace"]\n print(names[0], "\\n")\n}\n</code></pre><p>A struct gives names to fixed fields:</p><pre><code class=\"language-capy\">struct Point\n{\n x : s32\n y : s32\n}\n\nfunction RENDER()\n{\n var point := Point(3, 4)\n print(point.x, " ", point.y, "\\n")\n}\n</code></pre><h2>Copy or share</h2><p>Numbers and booleans are copied: after <code>var b := a</code>, changing <code>b</code> leaves <code>a</code> alone. Strings are values too. A string never changes in place, so it makes no difference whether two names share one.</p><p>Arrays, structs, and dvals are objects. <code>var b := a</code> makes <code>b</code> a second name for the same object, and so do parameters, return values, closure captures, and member reads. A change made through one name shows through all of them. When you need a separate copy, <code>clone(value)</code> makes one.</p><p>A variable can be pointed at another object with <code>=</code>. A parameter cannot.</p><p>The collections chapter covers arrays and structs in detail, the dynamic values chapter covers <code>dval</code>.</p><h2>Numeric functions</h2><p>Use the <code>math</code> functions for floating-point calculations and numeric bounds. Use the <code>bits</code> functions for")
|
||||
print(" integer masks, shifts, rotations, counts, and bit reinterpretation.</p><p>See the <code>math</code> function reference for floating-point operations and predicates. See the <code>bits</code> function reference for integer bit operations and floating-point bit reinterpretation.</p><h2>Dynamic values and none</h2><p>A <code>dval</code> holds data whose shape is known only at run time. The <code>none</code> value represents missing dynamic data:</p><pre><code class=\"language-capy\">function RENDER()\n{\n var profile := { name: "Ada" }\n var missing := none\n print(profile.name, " ", missing?, "\\n")\n}\n</code></pre><p><code>none</code> is different from <code>""</code>, <code>false</code>, an empty map, and an empty list. A <code>dval</code> is also an object that variables refer to, never a copy. The dynamic-values chapter explains mutation, safe reads, and conversions.</p><h2>Type aliases and static type names</h2><p>A type alias gives another name to a type. It does not create a distinct type at runtime.</p><p>Use <code>expression::type_name</code> to get the resolved static type of an expression. Capy evaluates the expression once.</p><pre><code class=\"language-capy\">type Count = s64\n\nfunction RENDER()\n{\n var total : Count = 12\n var labels := ["new", "done"]\n print(total::type_name, " ", labels::type_name, "\\n")\n}\n</code></pre><p><strong>Output</strong></p><pre><code class=\"language-text\">s64 [string]\n</code></pre><p>An alias reports its target type. Arrays use <code>[item_type]</code>. Structs use their declared name. Function values use their complete function type.</p><p>A <code>dval</code> expression reports <code>dval</code>, regardless of its current contents. Use <code>get_type_name(value)")
|
||||
print("</code> to inspect the value stored inside a <code>dval</code>.</p><h2>Struct field inspection</h2><p>Struct values have two additional reflection expressions:</p><table><thead><tr><th>Expression</th><th>Result</th><th>Meaning</th></tr></thead><tbody><tr><td><code>value::size</code></td><td><code>s64</code></td><td>The number of declared fields. This is not a byte size.</td></tr><tr><td><code>value::items</code></td><td><code>dval</code></td><td>A new map of the current field values, keyed by field name.</td></tr></tbody></table><p>Each <code>items</code> entry contains <code>value</code> and <code>type_name</code>. Use <code>fields.name.value</code> for a fixed field. Use <code>fields[key]["value"]</code> for a dynamic field name.</p><p><code>value::items</code> evaluates its receiver once. Changing the returned map does not change the struct. The compiler rejects <code>size</code> and <code>items</code> on non-struct values.</p><p>The struct reference defines field conversions for scalars, strings, DValues, nested structs, arrays, and function values.</p><h2>Dependent generic types</h2><p>A generic function can use the concrete type of an earlier <code>any</code> parameter. Write <code>parameter::type</code> in a later parameter or the function result:</p><pre><code class=\"language-capy\">function same(first : any, second : first::type) first::type\n{\n -> second\n}</code></pre><p><code>parameter::type</code> is a compile-time type expression. It does not inspect a runtime value. The compiler rejects the removed <code>type(parameter)</code> spelling.</p></div><nav class=\"guide-navigation\" aria-label=\"Capy guide navigation\"><div class=\"guide-previous\">Previous: <a href=\"/doc/guide/source-structure-and-syntax/\">2. Basic syntax</a></div><div class=\"guide-index\">")
|
||||
print("<a href=\"/doc/\">Guide index</a></div><div class=\"guide-next\">Next: <a href=\"/doc/guide/expressions-and-control-flow/\">4. Expressions and control flow</a></div></nav></main><aside class=\"doc-section see-also\"><h3>See also</h3><a class=\"related-link\" href=\"/doc/guide/install-and-first-program/\">1. Getting started</a><a class=\"related-link\" href=\"/doc/guide/source-structure-and-syntax/\">2. Basic syntax</a><a class=\"related-link\" href=\"/doc/guide/expressions-and-control-flow/\">4. Expressions and control flow</a><a class=\"related-link\" href=\"/doc/guide/functions-and-closures/\">5. Functions</a><a class=\"related-link\" href=\"/doc/guide/strings-and-markup/\">6. Strings and HTML</a><a class=\"related-link\" href=\"/doc/guide/collections-and-records/\">7. Arrays and structs</a><a class=\"related-link\" href=\"/doc/guide/dynamic-values/\">8. Dynamic values</a><a class=\"related-link\" href=\"/doc/guide/web-handlers-and-requests/\">9. Handling a web request</a><a class=\"related-link\" href=\"/doc/guide/units-components-and-exports/\">10. Units and components</a><a class=\"related-link\" href=\"/doc/guide/tasks-and-commands/\">11. Tasks and commands</a><a class=\"related-link\" href=\"/doc/guide/services/\">12. Services</a><a class=\"related-link\" href=\"/doc/guide/errors-testing-and-style/\">13. Errors and testing</a><a class=\"related-link\" href=\"/doc/guide/coming-from-react/\">14. Coming from React</a><a class=\"related-link\" href=\"/doc/type/dvalue/\">Dynamic values</a><a class=\"related-link\" href=\"/doc/type/struct/\">struct</a><a class=\"related-link\" href=\"/doc/api/get-type-name/\">get_type_name</a><a class=\"related-link\" href=\"/doc/type/bool/\">bool</a><a class=\"related-link\" href=\"/doc/type/s8/\">s8</a><a class=\"related-link\" href=\"/doc/type/s16/\">s16</a><a class=\"related-link\" href=\"/doc/type/s32/\">s32</a><a cl")
|
||||
print("ass=\"related-link\" href=\"/doc/type/s64/\">s64</a><a class=\"related-link\" href=\"/doc/type/u8/\">u8</a><a class=\"related-link\" href=\"/doc/type/u16/\">u16</a><a class=\"related-link\" href=\"/doc/type/u32/\">u32</a><a class=\"related-link\" href=\"/doc/type/u64/\">u64</a><a class=\"related-link\" href=\"/doc/type/f32/\">f32</a><a class=\"related-link\" href=\"/doc/type/f64/\">f64</a><a class=\"related-link\" href=\"/doc/api/string/\">string</a><a class=\"related-link\" href=\"/doc/api/dval/\">dval</a><a class=\"related-link\" href=\"/doc/api/length/\">length</a><a class=\"related-link\" href=\"/doc/api/sqrt/\">sqrt</a><a class=\"related-link\" href=\"/doc/api/bit-and/\">bit_and</a></aside></div>")
|
||||
print("</code> to inspect the value stored inside a <code>dval</code>.</p><h2>Struct field inspection</h2><p>Struct values have two additional reflection expressions:</p><table><thead><tr><th>Expression</th><th>Result</th><th>Meaning</th></tr></thead><tbody><tr><td><code>value::size</code></td><td><code>s64</code></td><td>The number of declared fields. This is not a byte size.</td></tr><tr><td><code>value::items</code></td><td><code>dval</code></td><td>A new map of the current field values, keyed by field name.</td></tr></tbody></table><p>Each <code>items</code> entry contains <code>value</code> and <code>type_name</code>. Use <code>fields.name.value</code> for a fixed field. Use <code>fields[key]["value"]</code> for a dynamic field name.</p><p><code>value::items</code> evaluates its receiver once. Changing the returned map does not change the struct. The compiler rejects <code>size</code> and <code>items</code> on non-struct values.</p><p>The struct reference defines field conversions for scalars, strings, DValues, nested structs, arrays, and function values.</p><h2>Dependent generic types</h2><p>A generic function can use the concrete type of an earlier <code>*</code> parameter. Write <code>parameter::type</code> in a later parameter or the function result:</p><pre><code class=\"language-capy\">function same(first : *, second : first::type) first::type\n{\n -> second\n}</code></pre><p><code>parameter::type</code> is a compile-time type expression. It does not inspect a runtime value. The compiler rejects the removed <code>type(parameter)</code> spelling.</p></div><nav class=\"guide-navigation\" aria-label=\"Capy guide navigation\"><div class=\"guide-previous\">Previous: <a href=\"/doc/guide/source-structure-and-syntax/\">2. Basic syntax</a></div><div class=\"guide-index\"><a h")
|
||||
print("ref=\"/doc/\">Guide index</a></div><div class=\"guide-next\">Next: <a href=\"/doc/guide/expressions-and-control-flow/\">4. Expressions and control flow</a></div></nav></main><aside class=\"doc-section see-also\"><h3>See also</h3><a class=\"related-link\" href=\"/doc/guide/install-and-first-program/\">1. Getting started</a><a class=\"related-link\" href=\"/doc/guide/source-structure-and-syntax/\">2. Basic syntax</a><a class=\"related-link\" href=\"/doc/guide/expressions-and-control-flow/\">4. Expressions and control flow</a><a class=\"related-link\" href=\"/doc/guide/functions-and-closures/\">5. Functions</a><a class=\"related-link\" href=\"/doc/guide/strings-and-markup/\">6. Strings and HTML</a><a class=\"related-link\" href=\"/doc/guide/collections-and-records/\">7. Arrays and structs</a><a class=\"related-link\" href=\"/doc/guide/dynamic-values/\">8. Dynamic values</a><a class=\"related-link\" href=\"/doc/guide/web-handlers-and-requests/\">9. Handling a web request</a><a class=\"related-link\" href=\"/doc/guide/units-components-and-exports/\">10. Units and components</a><a class=\"related-link\" href=\"/doc/guide/tasks-and-commands/\">11. Tasks and commands</a><a class=\"related-link\" href=\"/doc/guide/services/\">12. Services</a><a class=\"related-link\" href=\"/doc/guide/errors-testing-and-style/\">13. Errors and testing</a><a class=\"related-link\" href=\"/doc/guide/coming-from-react/\">14. Coming from React</a><a class=\"related-link\" href=\"/doc/type/dvalue/\">Dynamic values</a><a class=\"related-link\" href=\"/doc/type/struct/\">struct</a><a class=\"related-link\" href=\"/doc/api/get-type-name/\">get_type_name</a><a class=\"related-link\" href=\"/doc/type/bool/\">bool</a><a class=\"related-link\" href=\"/doc/type/s8/\">s8</a><a class=\"related-link\" href=\"/doc/type/s16/\">s16</a><a class=\"related-link\" href=\"/doc/type/s32/\">s32</a><a class=")
|
||||
print("\"related-link\" href=\"/doc/type/s64/\">s64</a><a class=\"related-link\" href=\"/doc/type/u8/\">u8</a><a class=\"related-link\" href=\"/doc/type/u16/\">u16</a><a class=\"related-link\" href=\"/doc/type/u32/\">u32</a><a class=\"related-link\" href=\"/doc/type/u64/\">u64</a><a class=\"related-link\" href=\"/doc/type/f32/\">f32</a><a class=\"related-link\" href=\"/doc/type/f64/\">f64</a><a class=\"related-link\" href=\"/doc/api/string/\">string</a><a class=\"related-link\" href=\"/doc/api/dval/\">dval</a><a class=\"related-link\" href=\"/doc/api/length/\">length</a><a class=\"related-link\" href=\"/doc/api/sqrt/\">sqrt</a><a class=\"related-link\" href=\"/doc/api/bit-and/\">bit_and</a></aside></div>")
|
||||
}
|
||||
@@ -204,7 +204,7 @@ inline constexpr DocCapySignature doc_capy_signatures[] = {
|
||||
{"floor", "function floor(value : f32) f32", "lib"},
|
||||
{"floor", "function floor(value : f64) f64", "lib"},
|
||||
{"flush_output", "function flush_output() bool", "host"},
|
||||
{"gen_noise", "function gen_noise(min : any, max : min::type, index : u64, seed : u64) min::type", "host"},
|
||||
{"gen_noise", "function gen_noise(min : *, max : min::type, index : u64, seed : u64) min::type", "host"},
|
||||
{"gen_noise64", "function gen_noise64(index : u64, seed : u64 = 0) u64", "host"},
|
||||
{"gen_sha1", "function gen_sha1(value : string) string", "lib"},
|
||||
{"get", "function get(value : dval, key : string) dval", "lib"},
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
:sig
|
||||
function gen_noise(min : any, max : min::type, index : u64, seed : u64) min::type
|
||||
function gen_noise(min : *, max : min::type, index : u64, seed : u64) min::type
|
||||
|
||||
:params
|
||||
min : first range value
|
||||
|
||||
@@ -175,10 +175,10 @@ The struct reference defines field conversions for scalars, strings, DValues, ne
|
||||
|
||||
## Dependent generic types
|
||||
|
||||
A generic function can use the concrete type of an earlier `any` parameter. Write `parameter::type` in a later parameter or the function result:
|
||||
A generic function can use the concrete type of an earlier `*` parameter. Write `parameter::type` in a later parameter or the function result:
|
||||
|
||||
```capy
|
||||
function same(first : any, second : first::type) first::type
|
||||
function same(first : *, second : first::type) first::type
|
||||
{
|
||||
-> second
|
||||
}
|
||||
|
||||
@@ -227,7 +227,7 @@ The function type must match exactly. A mismatch traps. A callable does not cros
|
||||
|
||||
## Generic and variadic functions
|
||||
|
||||
An `any` parameter creates a compile-time generic function. Use it when the same operation is valid for several concrete types.
|
||||
A `*` parameter creates a compile-time generic function. Use it when the same operation is valid for several concrete types.
|
||||
|
||||
A variadic parameter collects values into a typed array:
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ function select(value : as s64) s32
|
||||
{
|
||||
-> 2
|
||||
}
|
||||
function choose(value : any) value::type
|
||||
function choose(value : *) value::type
|
||||
{
|
||||
-> value
|
||||
}
|
||||
|
||||
@@ -21,7 +21,7 @@ function describe(value : string) string
|
||||
{
|
||||
-> "string"
|
||||
}
|
||||
function identity(value : any) value::type
|
||||
function identity(value : *) value::type
|
||||
{
|
||||
-> value
|
||||
}
|
||||
|
||||
@@ -30,12 +30,12 @@ function subtract(left : s32, right : s32) s32
|
||||
-> left - right
|
||||
}
|
||||
|
||||
function identity(value : any) value::type
|
||||
function identity(value : *) value::type
|
||||
{
|
||||
-> value
|
||||
}
|
||||
|
||||
function choose(value : any) value::type
|
||||
function choose(value : *) value::type
|
||||
{
|
||||
-> value
|
||||
}
|
||||
@@ -45,7 +45,7 @@ function choose(value : s32) value::type
|
||||
-> value + 1
|
||||
}
|
||||
|
||||
function same(first : any, second : first::type) first::type
|
||||
function same(first : *, second : first::type) first::type
|
||||
{
|
||||
-> second
|
||||
}
|
||||
@@ -65,7 +65,7 @@ function pair_label(value : TextPair) string
|
||||
-> value.text
|
||||
}
|
||||
|
||||
function countdown(value : any) value::type
|
||||
function countdown(value : *) value::type
|
||||
{
|
||||
if value == 0
|
||||
{
|
||||
|
||||
+18
-18
@@ -458,8 +458,8 @@ std::string type_of_expression(const Expr* expression, bool allow_void = false)
|
||||
return type + ") " + type_of_expression(function->return_type, true);
|
||||
}
|
||||
std::string name = type_name(*expression);
|
||||
if (name == "any" || name.find("::type") != std::string::npos)
|
||||
throw Error(expression->location, "compile-time any and dependent types are only valid in a generic function declaration");
|
||||
if (name == "*" || name.find("::type") != std::string::npos)
|
||||
throw Error(expression->location, "compile-time * and dependent types are only valid in a generic function declaration");
|
||||
if (name == "s8" || name == "s16" || name == "s32" || name == "s64" || name == "u8" || name == "u16" || name == "u32" || name == "u64" || name == "f32" || name == "f64" || name == "bool" || name == "string" || name == "dval" ||
|
||||
name == "module" || name == "void")
|
||||
return name;
|
||||
@@ -615,7 +615,7 @@ bool generic_matches(const GenericDefinition& generic, const std::vector<std::st
|
||||
for (std::size_t i = 0; i < types.size(); ++i)
|
||||
{
|
||||
const int dependency = generic.dependent_parameters[i];
|
||||
if (dependency < 0 && generic.patterns[i] == "any")
|
||||
if (dependency < 0 && generic.patterns[i] == "*")
|
||||
continue;
|
||||
if ((dependency >= 0 && types[i] != types[static_cast<std::size_t>(dependency)]) ||
|
||||
(dependency < 0 && generic.patterns[i] != types[i]))
|
||||
@@ -1153,7 +1153,7 @@ struct Module
|
||||
resolving_defaults.erase(request);
|
||||
if (auto found = generics_.find(name); found != generics_.end())
|
||||
for (const GenericDefinition& generic : found->second)
|
||||
if (generic.patterns.size() == 1 && (generic.patterns[0] == "any" || generic.patterns[0] == source))
|
||||
if (generic.patterns.size() == 1 && (generic.patterns[0] == "*" || generic.patterns[0] == source))
|
||||
{
|
||||
const std::string result = generic.dependent_result == 0 ? source : generic.fixed_result;
|
||||
if (result == target)
|
||||
@@ -7115,7 +7115,7 @@ void Module::collect()
|
||||
for (Expr* item : items_)
|
||||
if (auto alias = dynamic_cast<TypeAlias*>(item))
|
||||
{
|
||||
if (alias->name == "true" || alias->name == "false" || alias->name == "any" ||
|
||||
if (alias->name == "true" || alias->name == "false" || alias->name == "*" ||
|
||||
alias->name == "s8" || alias->name == "s16" || alias->name == "s32" || alias->name == "s64" || alias->name == "u8" || alias->name == "u16" || alias->name == "u32" || alias->name == "u64" || alias->name == "f32" || alias->name == "f64" || alias->name == "bool" ||
|
||||
alias->name == "string" || alias->name == "dval" || alias->name == "module" || alias->name == "void")
|
||||
throw Error(alias->location, "type alias name '" + alias->name + "' is reserved");
|
||||
@@ -7242,7 +7242,7 @@ void Module::collect()
|
||||
for (std::size_t parameter_index = 0; parameter_index < function->parameters.size(); ++parameter_index)
|
||||
{
|
||||
const auto& parameter = function->parameters[parameter_index];
|
||||
const bool any = dynamic_cast<Name*>(parameter.type_expr) && static_cast<Name*>(parameter.type_expr)->value == "any";
|
||||
const bool wildcard = dynamic_cast<Name*>(parameter.type_expr) && static_cast<Name*>(parameter.type_expr)->value == "*";
|
||||
const auto dependency_name = dependent_type_parameter(parameter.type_expr);
|
||||
int dependency = -1;
|
||||
if (dependency_name)
|
||||
@@ -7252,14 +7252,14 @@ void Module::collect()
|
||||
if (dependency < 0)
|
||||
throw Error(parameter.type_expr->location, "dependent type names an unknown or forward parameter");
|
||||
const Expr* source_type = function->parameters[static_cast<std::size_t>(dependency)].type_expr;
|
||||
if (!(dynamic_cast<const Name*>(source_type) && type_name(*source_type) == "any"))
|
||||
throw Error(parameter.type_expr->location, "dependent type requires an earlier any parameter");
|
||||
if (!(dynamic_cast<const Name*>(source_type) && type_name(*source_type) == "*"))
|
||||
throw Error(parameter.type_expr->location, "dependent type requires an earlier * parameter");
|
||||
}
|
||||
generic = generic || any || dependency >= 0;
|
||||
generic = generic || wildcard || dependency >= 0;
|
||||
dependent_parameters.push_back(dependency);
|
||||
std::string type;
|
||||
if (any || dependency >= 0)
|
||||
type = "any";
|
||||
if (wildcard || dependency >= 0)
|
||||
type = "*";
|
||||
else
|
||||
type = value_type(parameter.type_expr);
|
||||
if (parameter.variadic)
|
||||
@@ -7274,9 +7274,9 @@ void Module::collect()
|
||||
conversions.push_back(parameter.variadic ? false : parameter.convert);
|
||||
captures.push_back(parameter.capture);
|
||||
parameter_names.push_back(parameter.name);
|
||||
if (parameter.capture && (any || dependency >= 0))
|
||||
if (parameter.capture && (wildcard || dependency >= 0))
|
||||
throw Error(parameter.type_expr->location, "a capture parameter needs a concrete type");
|
||||
if (parameter.convert && (any || !dynamic_cast<Name*>(parameter.type_expr)))
|
||||
if (parameter.convert && (wildcard || !dynamic_cast<Name*>(parameter.type_expr)))
|
||||
throw Error(parameter.type_expr->location, "'as' parameter conversion requires a concrete named type constructor");
|
||||
if (parameters.back() == "void")
|
||||
throw Error(parameter.type_expr->location, "function parameters cannot have type void");
|
||||
@@ -7294,13 +7294,13 @@ void Module::collect()
|
||||
if (variadic && function->host)
|
||||
throw Error(function->location, "host declarations cannot use variadic parameters");
|
||||
if (variadic && generic)
|
||||
throw Error(function->location, "variadic parameters cannot use any yet");
|
||||
throw Error(function->location, "variadic parameters cannot use * yet");
|
||||
if (handler && variadic)
|
||||
throw Error(function->location, "Bearer handlers cannot use variadic parameters");
|
||||
if (handler && std::any_of(default_values.begin(), default_values.end(), [](Expr* value) { return value; }))
|
||||
throw Error(function->location, "Bearer handlers cannot use default parameters");
|
||||
if (handler && generic)
|
||||
throw Error(function->location, "Bearer handlers cannot use any parameters");
|
||||
throw Error(function->location, "Bearer handlers cannot use * parameters");
|
||||
if (handler && std::any_of(conversions.begin(), conversions.end(), [](bool value) { return value; }))
|
||||
throw Error(function->location, "Bearer handlers cannot request parameter conversion");
|
||||
if (handler && std::any_of(captures.begin(), captures.end(), [](bool value) { return value; }))
|
||||
@@ -7368,8 +7368,8 @@ void Module::collect()
|
||||
throw Error(function->return_type->location, "dependent result names an unknown parameter");
|
||||
if (dependent_parameters[static_cast<std::size_t>(dependent)] < 0 &&
|
||||
!(dynamic_cast<Name*>(function->parameters[static_cast<std::size_t>(dependent)].type_expr) &&
|
||||
type_name(*function->parameters[static_cast<std::size_t>(dependent)].type_expr) == "any"))
|
||||
throw Error(function->return_type->location, "dependent result requires an any parameter");
|
||||
type_name(*function->parameters[static_cast<std::size_t>(dependent)].type_expr) == "*"))
|
||||
throw Error(function->return_type->location, "dependent result requires a * parameter");
|
||||
}
|
||||
else
|
||||
fixed_result = value_type(function->return_type, true);
|
||||
@@ -8389,7 +8389,7 @@ Module::Capabilities Module::discover_capabilities()
|
||||
scan_string_names.clear();
|
||||
scan_value_names.clear();
|
||||
for (std::size_t i = 0; i < generic.function->parameters.size(); ++i)
|
||||
if (generic.patterns[i] != "any")
|
||||
if (generic.patterns[i] != "*")
|
||||
{
|
||||
const std::string& type = generic.patterns[i];
|
||||
if (type == "string")
|
||||
|
||||
@@ -741,6 +741,8 @@ Expr* Parser::prefix()
|
||||
return while_expr(current.location);
|
||||
return program_.make<Name>(current.location, current.text);
|
||||
}
|
||||
if (current.text == "*")
|
||||
return program_.make<Name>(current.location, current.text);
|
||||
if (current.text == "->")
|
||||
return result_expr(current.location, true);
|
||||
if (current.text == "...")
|
||||
@@ -1359,6 +1361,7 @@ std::string format_source(std::string_view source)
|
||||
const bool unary_minus = is_symbol(token, "-") && !value_end;
|
||||
if (is_symbol(token, "..") || is_symbol(token, "...")) { write(text); continue; }
|
||||
if (is_symbol(token, "!") || unary_minus) { if (before && before->kind == TokenKind::identifier) space(); write(text); continue; }
|
||||
if (is_symbol(token, "*") && before && is_symbol(*before, ":")) { write(text); continue; }
|
||||
if (token.kind == TokenKind::symbol) { space(); write(text); space(); continue; }
|
||||
if (before && (before->kind == TokenKind::identifier || before->kind == TokenKind::integer || before->kind == TokenKind::floating || before->kind == TokenKind::string || before->kind == TokenKind::markup || is_symbol(*before, ")") || is_symbol(*before, "]") || is_symbol(*before, "}"))) space();
|
||||
write(raw(token));
|
||||
|
||||
@@ -889,7 +889,7 @@ function mysql_info(handle : u64, key : string) dval {
|
||||
function random_bytes(count : u64) string { -> __bearer_random_bytes(count) }
|
||||
function __gen_noise(min : u64, max : u64, index : u64, seed : u64) u64 { -> __bearer_noise_u64(__bearer_noise_gen_int(), min, max, index, seed) }
|
||||
function __gen_noise(min : f64, max : f64, index : u64, seed : u64) f64 { -> __bearer_noise_f64(__bearer_noise_gen_float(), min, max, index, seed, 0.000000000001) }
|
||||
function gen_noise(min : any, max : min::type, index : u64, seed : u64) min::type { -> __gen_noise(min, max, index, seed) }
|
||||
function gen_noise(min : *, max : min::type, index : u64, seed : u64) min::type { -> __gen_noise(min, max, index, seed) }
|
||||
function gen_noise64(index : u64, seed : u64 = 0) u64 { -> __bearer_noise_u64(__bearer_noise_gen_noise64(), index, seed, 0, 0) }
|
||||
function draw_int(from : u64, to : u64) u64 { -> __bearer_noise_u64(__bearer_noise_draw_int(), from, to, 0, 0) }
|
||||
function draw_float(from : f64, to : f64, precision : f64 = 0.000000000001) f64 { -> __bearer_noise_f64(__bearer_noise_draw_float(), from, to, 0, 0, precision) }
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
#pragma once
|
||||
#include <string_view>
|
||||
namespace capy::stdlib {
|
||||
inline constexpr char digest[] __attribute__((used)) = "003ab3997ed254da057b2bd074a8d5898b3d5517006bcb1f90a30bcc7d52436a";
|
||||
inline constexpr unsigned char source[] = {47,47,32,80,114,105,118,97,116,101,32,116,121,112,101,100,32,104,111,115,116,32,65,66,73,32,100,101,99,108,97,114,97,116,105,111,110,115,46,32,32,78,97,109,101,115,32,109,97,112,32,100,105,114,101,99,116,108,121,32,116,111,32,101,110,118,32,115,121,109,98,111,108,115,46,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,112,114,105,110,116,95,98,121,116,101,115,40,118,97,108,117,101,32,58,32,115,116,114,105,110,103,41,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,102,108,117,115,104,95,111,117,116,112,117,116,40,41,32,98,111,111,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,112,111,119,95,102,51,50,40,98,97,115,101,32,58,32,102,51,50,44,32,101,120,112,111,110,101,110,116,32,58,32,102,51,50,41,32,102,51,50,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,112,111,119,95,102,54,52,40,98,97,115,101,32,58,32,102,54,52,44,32,101,120,112,111,110,101,110,116,32,58,32,102,54,52,41,32,102,54,52,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,108,111,103,95,102,51,50,40,118,97,108,117,101,32,58,32,102,51,50,41,32,102,51,50,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,108,111,103,95,102,54,52,40,118,97,108,117,101,32,58,32,102,54,52,41,32,102,54,52,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,101,120,112,95,102,51,50,40,118,97,108,117,101,32,58,32,102,51,50,41,32,102,51,50,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,101,120,112,95,102,54,52,40,118,97,108,117,101,32,58,32,102,54,52,41,32,102,54,52,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,115,105,110,95,102,51,50,40,118,97,108,117,101,32,58,32,102,51,50,41,32,102,51,50,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,115,105,110,95,102,54,52,40,118,97,108,117,101,32,58,32,102,54,52,41,32,102,54,52,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,99,111,115,95,102,51,50,40,118,97,108,117,101,32,58,32,102,51,50,41,32,102,51,50,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,99,111,115,95,102,54,52,40,118,97,108,117,101,32,58,32,102,54,52,41,32,102,54,52,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,97,116,97,110,50,95,102,51,50,40,121,32,58,32,102,51,50,44,32,120,32,58,32,102,51,50,41,32,102,51,50,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,97,116,97,110,50,95,102,54,52,40,121,32,58,32,102,54,52,44,32,120,32,58,32,102,54,52,41,32,102,54,52,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,95,110,111,110,101,40,41,32,100,118,97,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,99,97,112,121,95,114,101,102,108,101,99,116,95,115,116,114,117,99,116,40,111,98,106,101,99,116,32,58,32,115,51,50,44,32,109,101,109,111,114,121,95,98,97,115,101,32,58,32,115,51,50,44,32,115,116,114,117,99,116,95,100,101,115,99,114,105,112,116,111,114,95,111,102,102,115,101,116,32,58,32,115,51,50,41,32,100,118,97,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,95,105,115,95,110,111,110,101,40,118,97,108,117,101,32,58,32,100,118,97,108,41,32,98,111,111,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,95,114,101,113,117,105,114,101,40,118,97,108,117,101,32,58,32,100,118,97,108,44,32,112,97,116,104,32,58,32,115,116,114,105,110,103,41,32,100,118,97,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,95,115,101,116,95,112,97,116,104,40,118,97,108,117,101,32,58,32,100,118,97,108,44,32,112,97,116,104,32,58,32,100,118,97,108,44,32,114,101,112,108,97,99,101,109,101,110,116,32,58,32,100,118,97,108,41,32,100,118,97,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,95,97,112,112,108,121,40,111,112,101,114,97,116,105,111,110,32,58,32,115,51,50,44,32,118,97,108,117,101,32,58,32,100,118,97,108,44,32,107,101,121,32,58,32,115,116,114,105,110,103,44,32,97,114,103,117,109,101,110,116,32,58,32,100,118,97,108,41,32,100,118,97,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,97,108,95,114,101,112,108,97,99,101,40,116,97,114,103,101,116,32,58,32,100,118,97,108,44,32,114,101,112,108,97,99,101,109,101,110,116,32,58,32,100,118,97,108,41,32,100,118,97,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,95,101,120,116,114,97,99,116,95,115,116,114,105,110,103,40,118,97,108,117,101,32,58,32,100,118,97,108,44,32,102,97,108,108,98,97,99,107,32,58,32,115,116,Line truncated
|
||||
inline constexpr char digest[] __attribute__((used)) = "7626bbf3b48afc319f5e25d991f31c55e9e1b65c72fbba80d5b1eab66692823b";
|
||||
inline constexpr unsigned char source[] = {47,47,32,80,114,105,118,97,116,101,32,116,121,112,101,100,32,104,111,115,116,32,65,66,73,32,100,101,99,108,97,114,97,116,105,111,110,115,46,32,32,78,97,109,101,115,32,109,97,112,32,100,105,114,101,99,116,108,121,32,116,111,32,101,110,118,32,115,121,109,98,111,108,115,46,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,112,114,105,110,116,95,98,121,116,101,115,40,118,97,108,117,101,32,58,32,115,116,114,105,110,103,41,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,102,108,117,115,104,95,111,117,116,112,117,116,40,41,32,98,111,111,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,112,111,119,95,102,51,50,40,98,97,115,101,32,58,32,102,51,50,44,32,101,120,112,111,110,101,110,116,32,58,32,102,51,50,41,32,102,51,50,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,112,111,119,95,102,54,52,40,98,97,115,101,32,58,32,102,54,52,44,32,101,120,112,111,110,101,110,116,32,58,32,102,54,52,41,32,102,54,52,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,108,111,103,95,102,51,50,40,118,97,108,117,101,32,58,32,102,51,50,41,32,102,51,50,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,108,111,103,95,102,54,52,40,118,97,108,117,101,32,58,32,102,54,52,41,32,102,54,52,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,101,120,112,95,102,51,50,40,118,97,108,117,101,32,58,32,102,51,50,41,32,102,51,50,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,101,120,112,95,102,54,52,40,118,97,108,117,101,32,58,32,102,54,52,41,32,102,54,52,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,115,105,110,95,102,51,50,40,118,97,108,117,101,32,58,32,102,51,50,41,32,102,51,50,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,115,105,110,95,102,54,52,40,118,97,108,117,101,32,58,32,102,54,52,41,32,102,54,52,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,99,111,115,95,102,51,50,40,118,97,108,117,101,32,58,32,102,51,50,41,32,102,51,50,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,99,111,115,95,102,54,52,40,118,97,108,117,101,32,58,32,102,54,52,41,32,102,54,52,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,97,116,97,110,50,95,102,51,50,40,121,32,58,32,102,51,50,44,32,120,32,58,32,102,51,50,41,32,102,51,50,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,97,116,97,110,50,95,102,54,52,40,121,32,58,32,102,54,52,44,32,120,32,58,32,102,54,52,41,32,102,54,52,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,95,110,111,110,101,40,41,32,100,118,97,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,99,97,112,121,95,114,101,102,108,101,99,116,95,115,116,114,117,99,116,40,111,98,106,101,99,116,32,58,32,115,51,50,44,32,109,101,109,111,114,121,95,98,97,115,101,32,58,32,115,51,50,44,32,115,116,114,117,99,116,95,100,101,115,99,114,105,112,116,111,114,95,111,102,102,115,101,116,32,58,32,115,51,50,41,32,100,118,97,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,95,105,115,95,110,111,110,101,40,118,97,108,117,101,32,58,32,100,118,97,108,41,32,98,111,111,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,95,114,101,113,117,105,114,101,40,118,97,108,117,101,32,58,32,100,118,97,108,44,32,112,97,116,104,32,58,32,115,116,114,105,110,103,41,32,100,118,97,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,95,115,101,116,95,112,97,116,104,40,118,97,108,117,101,32,58,32,100,118,97,108,44,32,112,97,116,104,32,58,32,100,118,97,108,44,32,114,101,112,108,97,99,101,109,101,110,116,32,58,32,100,118,97,108,41,32,100,118,97,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,95,97,112,112,108,121,40,111,112,101,114,97,116,105,111,110,32,58,32,115,51,50,44,32,118,97,108,117,101,32,58,32,100,118,97,108,44,32,107,101,121,32,58,32,115,116,114,105,110,103,44,32,97,114,103,117,109,101,110,116,32,58,32,100,118,97,108,41,32,100,118,97,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,97,108,95,114,101,112,108,97,99,101,40,116,97,114,103,101,116,32,58,32,100,118,97,108,44,32,114,101,112,108,97,99,101,109,101,110,116,32,58,32,100,118,97,108,41,32,100,118,97,108,10,104,111,115,116,32,102,117,110,99,116,105,111,110,32,95,95,98,101,97,114,101,114,95,100,118,95,101,120,116,114,97,99,116,95,115,116,114,105,110,103,40,118,97,108,117,101,32,58,32,100,118,97,108,44,32,102,97,108,108,98,97,99,107,32,58,32,115,116,Line truncated
|
||||
inline const std::string_view text(reinterpret_cast<const char*>(source), sizeof(source));
|
||||
}
|
||||
+1
-1
@@ -1,7 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#define BEARER_WASM_CORE_ABI_VERSION 40
|
||||
#define BEARER_COMPILER_UNIT_ABI_VERSION 39
|
||||
#define BEARER_COMPILER_UNIT_ABI_VERSION 40
|
||||
|
||||
#define BEARER_WASM_OBJECT_WORD_SIZE 4
|
||||
#define BEARER_WASM_OBJECT_REFS_OFFSET 0
|
||||
|
||||
Reference in new issue
Block a user