Skip to content

Commit c0e2a0f

Browse files
committed
Very basic return types
1 parent 30325e3 commit c0e2a0f

10 files changed

Lines changed: 59 additions & 7 deletions

File tree

ndc_bin/src/docs.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,14 +67,16 @@ pub fn docs(query: Option<&str>) -> anyhow::Result<()> {
6767
}
6868
}
6969

70-
writeln!(signature, ")")?;
70+
write!(signature, ")")?;
7171
}
7272
}
7373
let name = function.name();
7474
let documentation = function.documentation().trim();
75+
let return_type = function.return_type();
7576
let markdown = format!(
76-
"---\n\n## **{}**{signature}\n{documentation}{}",
77+
"---\n\n## **{}**{signature} -> {}\n\n{documentation}{}",
7778
name.green(),
79+
format!("{}", return_type).green().bold(),
7880
if documentation.is_empty() { "" } else { "\n\n" }
7981
);
8082

ndc_lib/src/ast/expression.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
use crate::ast::operator::LogicalOperator;
22
use crate::ast::parser::Error as ParseError;
33
use crate::interpreter::evaluate::EvaluationError;
4+
use crate::interpreter::function::StaticType;
45
use crate::lexer::Span;
56
use num::BigInt;
67
use num::complex::Complex64;
@@ -57,6 +58,7 @@ pub enum Expression {
5758
resolved_name: Option<ResolvedVar>,
5859
parameters: Box<ExpressionLocation>,
5960
body: Box<ExpressionLocation>,
61+
return_type: Option<StaticType>,
6062
pure: bool,
6163
},
6264
Block {
@@ -332,15 +334,17 @@ impl std::fmt::Debug for ExpressionLocation {
332334
.finish(),
333335
Expression::FunctionDeclaration {
334336
name,
335-
parameters: arguments,
337+
parameters,
338+
return_type,
336339
body,
337340
pure,
338341
resolved_name,
339342
} => f
340343
.debug_struct("FunctionDeclaration")
341344
.field("name", name)
342345
.field("resolved_name", resolved_name)
343-
.field("arguments", arguments)
346+
.field("parameters", parameters)
347+
.field("return_type", return_type)
344348
.field("body", body)
345349
.field("pure", pure)
346350
.finish(),

ndc_lib/src/ast/parser.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1157,6 +1157,7 @@ impl Parser {
11571157
name: identifier,
11581158
parameters: Box::new(argument_list),
11591159
body: Box::new(body),
1160+
return_type: None, // At some point in the future we could use type declarations here to insert the type (return type inference is cringe anyway)
11601161
pure: is_pure,
11611162
resolved_name: None,
11621163
},

ndc_lib/src/interpreter/evaluate/mod.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,12 +348,14 @@ pub(crate) fn evaluate_expression(
348348
parameters: arguments,
349349
body,
350350
resolved_name,
351+
return_type,
351352
pure,
352353
..
353354
} => {
354355
let mut user_function = FunctionBody::Closure {
355356
parameter_names: arguments.try_into_parameters()?,
356357
body: *body.clone(),
358+
return_type: return_type.clone().unwrap_or_else(StaticType::unit),
357359
environment: environment.clone(),
358360
};
359361

ndc_lib/src/interpreter/function.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,13 +72,17 @@ impl Function {
7272
pub fn type_signature(&self) -> TypeSignature {
7373
self.body.type_signature()
7474
}
75+
pub fn return_type(&self) -> &StaticType {
76+
self.body.return_type()
77+
}
7578
}
7679

7780
#[derive(Clone)]
7881
pub enum FunctionBody {
7982
Closure {
8083
parameter_names: Vec<String>,
8184
body: ExpressionLocation,
85+
return_type: StaticType,
8286
environment: Rc<RefCell<Environment>>,
8387
},
8488
NumericUnaryOp {
@@ -89,6 +93,7 @@ pub enum FunctionBody {
8993
},
9094
GenericFunction {
9195
type_signature: TypeSignature,
96+
return_type: StaticType,
9297
function: fn(&mut [Value], &Rc<RefCell<Environment>>) -> EvaluationResult,
9398
},
9499
Memoized {
@@ -111,13 +116,16 @@ impl FunctionBody {
111116
}
112117
pub fn generic(
113118
type_signature: TypeSignature,
119+
return_type: StaticType,
114120
function: fn(&mut [Value], &Rc<RefCell<Environment>>) -> EvaluationResult,
115121
) -> Self {
116122
Self::GenericFunction {
117123
type_signature,
124+
return_type,
118125
function,
119126
}
120127
}
128+
121129
fn type_signature(&self) -> TypeSignature {
122130
match self {
123131
Self::Closure {
@@ -140,6 +148,15 @@ impl FunctionBody {
140148
}
141149
}
142150

151+
pub fn return_type(&self) -> &StaticType {
152+
match self {
153+
FunctionBody::Closure { return_type, .. } => return_type,
154+
FunctionBody::NumericUnaryOp { .. } => &StaticType::Number,
155+
FunctionBody::NumericBinaryOp { .. } => &StaticType::Number,
156+
FunctionBody::GenericFunction { return_type, .. } => return_type,
157+
FunctionBody::Memoized { function, .. } => function.return_type(),
158+
}
159+
}
143160
pub fn call(&self, args: &mut [Value], env: &Rc<RefCell<Environment>>) -> EvaluationResult {
144161
match self {
145162
Self::Closure {

ndc_lib/src/stdlib/file.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
use crate::interpreter::environment::Environment;
2-
use crate::interpreter::function::{FunctionBody, FunctionBuilder, FunctionCarrier, TypeSignature};
2+
use crate::interpreter::function::{
3+
FunctionBody, FunctionBuilder, FunctionCarrier, StaticType, TypeSignature,
4+
};
35
use crate::interpreter::value::Value;
46
use ndc_macros::export_module;
57
use std::fs::read_to_string;
@@ -46,6 +48,7 @@ pub fn register_variadic(env: &mut Environment) {
4648
Ok(Value::unit())
4749
},
4850
type_signature: TypeSignature::Variadic,
51+
return_type: StaticType::unit(),
4952
})
5053
.build()
5154
.expect("function definition defined in code must be valid"),
@@ -73,6 +76,7 @@ pub fn register_variadic(env: &mut Environment) {
7376
Ok(Value::unit())
7477
},
7578
type_signature: TypeSignature::Variadic,
79+
return_type: StaticType::unit(),
7680
})
7781
.build()
7882
.expect("function definition defined in code must be valid"),

ndc_lib/src/stdlib/math.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ pub mod f64 {
267267
},
268268
_ => unreachable!("the type checker should never invoke this function if the argument count does not match")
269269
},
270+
return_type: StaticType::Bool,
270271
})
271272
.build()
272273
.expect("must succeed")
@@ -291,6 +292,7 @@ pub mod f64 {
291292
[left, right] => Ok(Value::Bool(left == right)),
292293
_ => unreachable!("the type checker should never invoke this function if the argument count does not match")
293294
},
295+
return_type: StaticType::Bool,
294296
})
295297
.build()
296298
.expect("must succeed")
@@ -308,6 +310,7 @@ pub mod f64 {
308310
[left, right] => Ok(Value::Bool(left != right)),
309311
_ => unreachable!("the type checker should never invoke this function if the argument count does not match")
310312
},
313+
return_type: StaticType::Bool,
311314
})
312315
.build()
313316
.expect("must succeed")
@@ -330,6 +333,7 @@ pub mod f64 {
330333
},
331334
_ => unreachable!("the type checker should never invoke this function if the argument count does not match")
332335
},
336+
return_type: StaticType::Int,
333337
})
334338
.build()
335339
.expect("must succeed")
@@ -352,6 +356,7 @@ pub mod f64 {
352356
},
353357
_ => unreachable!("the type checker should never invoke this function if the argument count does not match")
354358
},
359+
return_type: StaticType::Int,
355360
})
356361
.build()
357362
.expect("must succeed")
@@ -371,6 +376,7 @@ pub mod f64 {
371376
[Value::Bool(left), Value::Bool(right)] => Ok(Value::Bool($operation(*left, *right))),
372377
_ => unreachable!("the type checker should never invoke this function if the argument count does not match")
373378
},
379+
return_type: StaticType::Bool,
374380
})
375381
.build()
376382
.expect("must succeed")
@@ -388,6 +394,7 @@ pub mod f64 {
388394
[Value::Number(Number::Int(left)), Value::Number(Number::Int(right))] => Ok(Value::Number(Number::Int($operation(left.clone(), right.clone())))),
389395
_ => unreachable!("the type checker should never invoke this function if the argument count does not match")
390396
},
397+
return_type: StaticType::Int,
391398
})
392399
.build()
393400
.expect("must succeed"),
@@ -416,6 +423,7 @@ pub mod f64 {
416423
[Value::Bool(b)] => Ok(Value::Bool(b.not())),
417424
_ => unreachable!("the type checker should never invoke this function if the argument count does not match"),
418425
},
426+
return_type: StaticType::Bool,
419427
})
420428
.name(ident.to_string())
421429
.build()
@@ -437,6 +445,7 @@ pub mod f64 {
437445
.map(|x| Value::Number(Number::Int(x))),
438446
_ => unreachable!("the type checker should never invoke this function if the argument count does not match")
439447
},
448+
return_type: StaticType::Int,
440449
})
441450
.build()
442451
.expect("must succeed")
@@ -456,6 +465,7 @@ pub mod f64 {
456465
.map(|x| Value::Number(Number::Int(x))),
457466
_ => unreachable!("the type checker should never invoke this function if the argument count does not match")
458467
},
468+
return_type: StaticType::Int,
459469
})
460470
.build()
461471
.expect("must succeed")

ndc_lib/src/stdlib/sequence.rs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -735,7 +735,7 @@ pub mod extra {
735735
use anyhow::anyhow;
736736
use itertools::izip;
737737

738-
use crate::interpreter::function::FunctionBuilder;
738+
use crate::interpreter::function::{FunctionBuilder, StaticType};
739739
use crate::interpreter::{
740740
environment::Environment, function::FunctionBody, iterator::mut_value_to_iterator,
741741
value::Value,
@@ -748,6 +748,7 @@ pub mod extra {
748748
.documentation("Combines multiple sequences (or iterables) into a single sequence of tuples, where the ith tuple contains the ith element from each input sequence.\n\nIf the input sequences are of different lengths, the resulting sequence is truncated to the length of the shortest input.".to_string())
749749
.body(FunctionBody::generic(
750750
crate::interpreter::function::TypeSignature::Variadic,
751+
StaticType::List,
751752
|args, _env| match args {
752753
[_] => {
753754
Err(anyhow!("zip must be called with 2 or more arguments").into())

ndc_macros/src/function.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,9 @@ pub fn wrap_function(function: &syn::ItemFn) -> Vec<WrappedFunction> {
5353
}
5454
}
5555

56+
// TODO: CONTINUE HERE
57+
let return_type = quote! { crate::interpreter::function::StaticType::Any }; // RIP ROP RAP
58+
5659
// If the function has no argument then the cartesian product stuff below doesn't work
5760
if function.sig.inputs.is_empty() {
5861
return function_names
@@ -63,6 +66,7 @@ pub fn wrap_function(function: &syn::ItemFn) -> Vec<WrappedFunction> {
6366
&original_identifier,
6467
function_name,
6568
vec![],
69+
return_type.clone(),
6670
&docs_buf,
6771
)
6872
})
@@ -71,7 +75,6 @@ pub fn wrap_function(function: &syn::ItemFn) -> Vec<WrappedFunction> {
7175

7276
// When we call create_temp_variable we can get multiple definitions for a variable
7377
// For instance when a rust function is `fn foo(list: &[Value])` we can define two internal functions for both Tuple and List
74-
7578
let mut variation_id = 0usize;
7679
function_names
7780
.iter()
@@ -98,6 +101,7 @@ pub fn wrap_function(function: &syn::ItemFn) -> Vec<WrappedFunction> {
98101
&format_ident!("{original_identifier}_{variation_id}"),
99102
function_name,
100103
args,
104+
return_type.clone(),
101105
&docs_buf,
102106
);
103107
variation_id += 1;
@@ -116,6 +120,7 @@ fn wrap_single(
116120
identifier: &syn::Ident,
117121
register_as_function_name: &proc_macro2::Literal,
118122
input_arguments: Vec<Argument>,
123+
return_type: TokenStream,
119124
docs: &str,
120125
) -> WrappedFunction {
121126
let inner_ident = format_ident!("{}_inner", identifier);
@@ -206,6 +211,7 @@ fn wrap_single(
206211
type_signature: crate::interpreter::function::TypeSignature::Exact(vec![
207212
#( crate::interpreter::function::Parameter::new(#param_names, #param_types,) ),*
208213
]),
214+
return_type: #return_type,
209215
})
210216
.name(String::from(#register_as_function_name))
211217
.documentation(String::from(#docs))
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
--PROGRAM--
2+
assert_eq((1,2).zip((3,4)), [(1,3),(2,4)]);
3+
print("ok");
4+
--EXPECT--
5+
ok

0 commit comments

Comments
 (0)