// Hover provider for the ƿit LSP. // Shows documentation for intrinsic functions and variable info. // Intrinsic function documentation database. // Each entry: {signature, description} def intrinsic_docs = { abs: { signature: "abs(number)", description: "Absolute value. Returns null for non-numbers." }, apply: { signature: "apply(function, array)", description: "Execute the function, passing array elements as input values." }, array: { signature: "array(value, ...)", description: "Create arrays. Polymorphic: array(number) creates sized array, array(array) copies, array(array, fn) maps, array(text) splits into characters, array(text, sep) splits by separator." }, ceiling: { signature: "ceiling(number, place)", description: "Round up. If place is 0 or null, round to smallest integer >= number." }, character: { signature: "character(value)", description: "If text, returns the first character. If a non-negative integer, returns the character from that codepoint." }, codepoint: { signature: "codepoint(text)", description: "Returns the codepoint number of the first character." }, ends_with: { signature: "ends_with(text, suffix)", description: "Returns true if the text ends with the given suffix." }, every: { signature: "every(array, function)", description: "Returns true if every element satisfies the predicate." }, extract: { signature: "extract(text, pattern, from, to)", description: "Match text to pattern. Returns a record of saved fields, or null if no match." }, fallback: { signature: "fallback(requestor_array)", description: "Returns a requestor that tries each requestor in order until one succeeds." }, filter: { signature: "filter(array, function)", description: "Returns a new array containing elements for which function returns true." }, find: { signature: "find(array, function, reverse, from)", description: "Returns the element number where function returns true, or null if not found. If second arg is not a function, compares directly." }, floor: { signature: "floor(number, place)", description: "Round down. If place is 0 or null, round to greatest integer <= number." }, format: { signature: "format(text, collection, transformer)", description: "Substitute {key} placeholders in text with values from a collection (array or record)." }, fraction: { signature: "fraction(number)", description: "Returns the fractional part of a number." }, is_array: { signature: "is_array(value)", description: "Returns true if the value is an array." }, is_blob: { signature: "is_blob(value)", description: "Returns true if the value is a blob." }, is_character: { signature: "is_character(value)", description: "Returns true if the value is a single character." }, is_data: { signature: "is_data(value)", description: "Returns true if the value is data (not a function)." }, is_digit: { signature: "is_digit(value)", description: "Returns true if the value is a digit character." }, is_false: { signature: "is_false(value)", description: "Returns true if the value is false." }, is_fit: { signature: "is_fit(value)", description: "Returns true if the value is a fit integer." }, is_function: { signature: "is_function(value)", description: "Returns true if the value is a function." }, is_integer: { signature: "is_integer(value)", description: "Returns true if the value is an integer." }, is_letter: { signature: "is_letter(value)", description: "Returns true if the value is a letter character." }, is_logical: { signature: "is_logical(value)", description: "Returns true if the value is a logical (boolean)." }, is_lower: { signature: "is_lower(value)", description: "Returns true if the value is a lowercase character." }, is_null: { signature: "is_null(value)", description: "Returns true if the value is null." }, is_number: { signature: "is_number(value)", description: "Returns true if the value is a number." }, is_object: { signature: "is_object(value)", description: "Returns true if the value is an object (record)." }, is_pattern: { signature: "is_pattern(value)", description: "Returns true if the value is a pattern (regex)." }, is_stone: { signature: "is_stone(value)", description: "Returns true if the value is frozen (stoned)." }, is_text: { signature: "is_text(value)", description: "Returns true if the value is text." }, is_true: { signature: "is_true(value)", description: "Returns true if the value is true." }, is_upper: { signature: "is_upper(value)", description: "Returns true if the value is an uppercase character." }, is_whitespace: { signature: "is_whitespace(value)", description: "Returns true if the value is a whitespace character." }, length: { signature: "length(value)", description: "Array: number of elements. Text: number of codepoints. Function: arity. Blob: number of bits. Record: record.length()." }, logical: { signature: "logical(value)", description: "Convert to logical. 0/false/null/\"false\" produce false; 1/true/\"true\" produce true." }, lower: { signature: "lower(text)", description: "Returns text with all uppercase characters converted to lowercase." }, max: { signature: "max(number, number)", description: "Returns the larger of two numbers." }, min: { signature: "min(number, number)", description: "Returns the smaller of two numbers." }, modulo: { signature: "modulo(dividend, divisor)", description: "Result has the sign of the divisor." }, neg: { signature: "neg(number)", description: "Negate. Reverse the sign of a number." }, normalize: { signature: "normalize(text)", description: "Unicode normalize." }, not: { signature: "not(logical)", description: "Returns the opposite logical. Returns null for non-logicals." }, number: { signature: "number(value, radix_or_format)", description: "Convert to number. Polymorphic: number(logical), number(text), number(text, radix), number(text, format)." }, parallel: { signature: "parallel(requestor_array, throttle, need)", description: "Start all requestors concurrently. Optional throttle limits concurrency; optional need specifies minimum successes." }, print: { signature: "print(value)", description: "Print a value to standard output." }, race: { signature: "race(requestor_array, throttle, need)", description: "Like parallel but returns as soon as needed results are obtained. Default need is 1." }, record: { signature: "record(value, ...)", description: "Create records. Polymorphic: record(record) copies, record(record, record) merges, record(array) creates from keys." }, reduce: { signature: "reduce(array, function, initial, reverse)", description: "Reduce an array to a single value by applying a function to pairs of elements." }, remainder: { signature: "remainder(dividend, divisor)", description: "For fit integers: dividend - ((dividend // divisor) * divisor)." }, replace: { signature: "replace(text, target, replacement, limit)", description: "Return text with target replaced. Target can be text or pattern. Replacement can be text or function." }, reverse: { signature: "reverse(array)", description: "Returns a new array with elements in the opposite order." }, round: { signature: "round(number, place)", description: "Round to nearest." }, search: { signature: "search(text, target, from)", description: "Search text for target. Returns character position or null." }, sequence: { signature: "sequence(requestor_array)", description: "Process requestors in order. Each result becomes input to the next." }, sign: { signature: "sign(number)", description: "Returns -1, 0, or 1." }, some: { signature: "some(array, function)", description: "Returns true if any element satisfies the predicate." }, sort: { signature: "sort(array, select)", description: "Returns a new sorted array. Sort keys must be all numbers or all texts. Ascending and stable." }, starts_with: { signature: "starts_with(text, prefix)", description: "Returns true if the text starts with the given prefix." }, stone: { signature: "stone(value)", description: "Petrify the value, making it permanently immutable. Deep freeze." }, text: { signature: "text(value, ...)", description: "Convert to text. Polymorphic: text(array, sep) joins, text(number, radix/format) formats, text(text, from, to) substrings." }, trim: { signature: "trim(text, reject)", description: "Remove characters from both ends. Default removes whitespace." }, trunc: { signature: "trunc(number, place)", description: "Truncate toward zero." }, upper: { signature: "upper(text)", description: "Returns text with all lowercase characters converted to uppercase." }, whole: { signature: "whole(number)", description: "Returns the whole part of a number." }, meme: { signature: "meme()", description: "Create a new meme (prototype chain marker)." }, proto: { signature: "proto(object, meme)", description: "Set the prototype meme of an object." }, isa: { signature: "isa(object, meme)", description: "Returns true if the object has the given meme in its prototype chain." }, splat: { signature: "splat(function, array)", description: "Call function with array elements as separate arguments." }, use: { signature: "use(path)", description: "Load a module. Returns the module's exported value. Modules are cached and frozen." }, pi: { signature: "pi", description: "An approximation of circumference / diameter: 3.1415926535897932." } } // Actor intrinsic documentation def actor_docs = { "$me": { signature: "$me", description: "The address of this actor." }, "$send": { signature: "$send(address, message)", description: "Send a message to another actor." }, "$start": { signature: "$start(script, env)", description: "Start a new actor from a script path." }, "$stop": { signature: "$stop()", description: "Stop this actor." }, "$delay": { signature: "$delay(milliseconds)", description: "Delay processing for a number of milliseconds." }, "$receiver": { signature: "$receiver(function)", description: "Set the message receiver function for this actor." }, "$clock": { signature: "$clock(interval, message)", description: "Send a message to self at regular intervals." }, "$portal": { signature: "$portal(name)", description: "Create a named portal for inter-actor communication." }, "$contact": { signature: "$contact(portal_name)", description: "Connect to a named portal." }, "$couple": { signature: "$couple(address)", description: "Couple with another actor for lifecycle management." }, "$unneeded": { signature: "$unneeded(function)", description: "Set a function to be called when this actor is no longer needed." }, "$connection": { signature: "$connection(address)", description: "Establish a connection with another actor." }, "$time_limit": { signature: "$time_limit(milliseconds)", description: "Set a time limit for this actor's execution." } } // Provide hover info for a token. var hover = function(doc, line, col, token_at) { var tok = token_at(doc, line, col) var info = null var name = null var _i = 0 var _j = 0 var scope = null var v = null if (tok == null) { return null } // Check intrinsic functions if (tok.kind == "name" && tok.value != null) { name = tok.value info = intrinsic_docs[name] if (info != null) { return { contents: { kind: "markdown", value: `**${info.signature}**\n\n${info.description}` } } } } // Check actor intrinsics ($name) if (tok.value != null && starts_with(tok.value, "$")) { info = actor_docs[tok.value] if (info != null) { return { contents: { kind: "markdown", value: `**${info.signature}**\n\n${info.description}` } } } } // Check keywords if (tok.kind == "var" || tok.kind == "def") { return { contents: { kind: "markdown", value: (tok.kind == "var") ? "**var** — Declare a mutable variable." : "**def** — Declare a constant." } } } if (tok.kind == "disrupt") { return { contents: { kind: "markdown", value: "**disrupt** — Raise an error. Use with **disruption** block to handle errors." } } } if (tok.kind == "disruption") { return { contents: { kind: "markdown", value: "**disruption** — Error handling block. Catches errors raised by **disrupt**." } } } // User variable: show declaration info from scope if (tok.kind == "name" && tok.value != null && doc.ast != null && doc.ast.scopes != null) { _i = 0 while (_i < length(doc.ast.scopes)) { scope = doc.ast.scopes[_i] if (scope.vars != null) { _j = 0 while (_j < length(scope.vars)) { v = scope.vars[_j] if (v.name == tok.value) { return { contents: { kind: "markdown", value: (v.is_const == true) ? `**def** ${v.name}` : `**var** ${v.name}` } } } _j = _j + 1 } } _i = _i + 1 } } return null } return { hover: hover, intrinsic_docs: intrinsic_docs, actor_docs: actor_docs }