Skip to content

Commit

Permalink
feat: hover info for builtin functions
Browse files Browse the repository at this point in the history
  • Loading branch information
viddrobnic committed Jul 30, 2024
1 parent e19c318 commit 83c03b5
Show file tree
Hide file tree
Showing 4 changed files with 261 additions and 4 deletions.
10 changes: 8 additions & 2 deletions language_server/src/analyze/document_info.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,15 @@ impl DocumentInfo {
}

pub fn get_documentation(&self, position: &Position) -> Option<&str> {
let def_at = self.get_definition(position)?;
let pos = self
.get_definition(position)
.map(|range| range.start)
// Fallback to given position. A hack to avoid traversing the syntax tree on hover
// request and compute the builtin function docs on request.
.unwrap_or(*position);

self.documentation
.get(&def_at.start)
.get(&pos)
.map(|entry| entry.entry.as_ref())
}
}
25 changes: 25 additions & 0 deletions language_server/src/analyze/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ use parser::{
ast,
position::{Position, Range},
};
use runtime::builtin::Builtin;
use symbol_table::SymbolTable;

pub mod document_info;
Expand Down Expand Up @@ -147,6 +148,16 @@ impl Analyzer {

fn resolve_ident(&mut self, ident: &str, location: Range) {
let Some(defined_at) = self.symbol_table.resolve(ident) else {
// The ident has not yet been defined. If we are using a ident
// that is not defined, it's probably a builtin function. Add documentation for builtin
// function at this poistion.
//
// If we have a lot of builtin function calls, we will copy the documentation for each call.
// This could be optimized by dynamicaly checking if request hover position
// is inside builtin function (in the textDocument/hover handler).
// I won't do this (for now), because it's a toy language and there is a lot
// of other things I want to try, before starting with optimizations :)
self.define_builtin_documentation(ident, location);
return;
};

Expand Down Expand Up @@ -239,6 +250,20 @@ impl Analyzer {
})
.unwrap();
}

fn define_builtin_documentation(&mut self, ident: &str, location: Range) {
let Some(builtin) = Builtin::from_ident(ident) else {
return;
};

self.document_info
.documentation
.push(LocationEntry {
location,
entry: builtin.documentation(),
})
.unwrap();
}
}

#[cfg(test)]
Expand Down
228 changes: 227 additions & 1 deletion runtime/src/builtin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,233 @@ impl Builtin {
Some(builtin)
}

pub fn call(&self, args: &[Object], gc: &mut GarbageCollector) -> Result<Object, ErrorKind> {
pub fn documentation(&self) -> String {
let doc = match self {
Builtin::Len => {
r#"
Returns length of the parameter. Parameter can be string, array or dictionary.
Usage:
```aoc
len([1, 2, 3]) // 3
```
"#
}
Builtin::Str => {
r#"
Returns string representation of the parameter. Paremeter can be int, bool, float or char.
Usage:
```aoc
str(10) // "10"
str(4.2) // "4.2"
str(true) // "true"
str(false) // "false"
str('a') // "a"
```
"#
}
Builtin::Int => {
r#"
Converts input to integer. Parameter can be float, string or char.
Usage:
```aoc
int(4.2) // 4
int("12") // 12
int('a') // 97
```
"#
}
Builtin::Char => {
r#"
Converts int to char.
Usage:
```aoc
char(97) // 'a'
```
"#
}
Builtin::Float => {
r#"
Converts parameter to float. Parameter can be int or string.
Usage:
```aoc
float(4) // 4.0
float("4.2") // 4.2
```
"#
}
Builtin::Bool => {
r#"
Returns weather the parameter is truthy. Everything except
`false` and `null` is truthy.
Usage:
```aoc
bool(false) // false
bool(null) // false
bool("") // true
```
"#
}
Builtin::IsNull => {
r#"
Returns if parameter is null.
Usage:
```aoc
is_null(null) // true
is_null(false) // false
```
"#
}
Builtin::Floor => {
r#"
Rounds down given float to the nearest integer.
Usage:
```aoc
floor(4.9) // 4.0
```
"#
}
Builtin::Ceil => {
r#"
Rounds up given float to the nearest integer.
Usage:
```aoc
ceil(4.1) // 5.0
```
"#
}
Builtin::Round => {
r#"
Rounds given float to the nearest integer.
Usage:
```aoc
round(4.2) // 4.0
round(4.5) // 5.0
round(4.8) // 5.0
```
"#
}
Builtin::TrimStart => {
r#"
Removes leading whitespace from string.
Usage:
```aoc
trim_start(" foo\n") // "foo\n"
```
"#
}
Builtin::TrimEnd => {
r#"
Removes trailing whitespace from string.
Usage:
```aoc
trim_end(" foo\n") // " foo"
```
"#
}
Builtin::Trim => {
r#"
Removes leading and trailing whitespace from string.
Usage:
```aoc
trim(" foo\n") // "foo"
```
"#
}
Builtin::Split => {
r#"
Splits the given string by a given delimeter.
Usage:
```aoc
split("foo", "") // ["f", "o", "o"]
split("foo bar", " ") // ["foo", "bar"]
```
"#
}
Builtin::Push => {
r#"
Adds element to the end of the array. Given array is mutated.
Usage:
```aoc
arr = []
push(arr, 1) // null
arr // [1]
```
"#
}
Builtin::Pop => {
r#"
Pops last element of the array and returns it. Given array is mutated.
If the array is empty, function returns `null`.
Usage:
```aoc
arr = [1]
pop(arr) // 1
arr // []
pop(arr) // null
```
"#
}
Builtin::Del => {
r#"
Deletes entry with given key in the dictionary. Deleted entry is returned.
If no entry under the key exists, `null` is returned.
Usage:
```aoc
dict = { "foo": "bar" }
del(dict, "foo") // "bar"
dict // {}
del(dict, "bar") // null
```
"#
}
Builtin::Print => {
r#"
Prints parameter to stdout. Parameter can be null, int, float, bool, string or char.
Usage:
```aoc
print("Hello world!") // Hello world!
```
"#
}
Builtin::Input => {
r#"
Reads a single line from stdin. If EOF is reached, `null` is returned.
The returned string doesn't contain trailing '\n'.
Usage:
```aoc
input()
```
"#
}
};

doc.to_string()
}

pub(crate) fn call(
&self,
args: &[Object],
gc: &mut GarbageCollector,
) -> Result<Object, ErrorKind> {
match self {
Builtin::Len => call_len(args),

Expand Down
2 changes: 1 addition & 1 deletion runtime/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
use parser::ast;

pub mod builtin;
pub mod compiler;
pub mod error;

mod builtin;
mod bytecode;
mod object;
mod vm;
Expand Down

0 comments on commit 83c03b5

Please sign in to comment.