Remove complex and compound constants.
This is not supported by the code generation, so it's a bit of a lie to have them in the language in the first place. There's arguably not even any use for constant records, list and tuples to begin with. So this cleans this up everywhere for the sake of moving forward with the alpha release. This now reduces constants to: - Integer - ByteArray - String Anything else can be declared via a function anyway. We can revisit this choice later.... or not.
This commit is contained in:
parent
560c17d5aa
commit
cd4ceb219c
|
@ -3,7 +3,7 @@ use std::{fmt, ops::Range, sync::Arc};
|
||||||
use crate::{
|
use crate::{
|
||||||
builtins::{self, bool},
|
builtins::{self, bool},
|
||||||
expr::{TypedExpr, UntypedExpr},
|
expr::{TypedExpr, UntypedExpr},
|
||||||
tipo::{fields::FieldMap, PatternConstructor, Type, TypeInfo, ValueConstructor},
|
tipo::{PatternConstructor, Type, TypeInfo},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const ASSERT_VARIABLE: &str = "_try";
|
pub const ASSERT_VARIABLE: &str = "_try";
|
||||||
|
@ -244,17 +244,17 @@ pub struct Use<PackageName> {
|
||||||
pub unqualified: Vec<UnqualifiedImport>,
|
pub unqualified: Vec<UnqualifiedImport>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TypedModuleConstant = ModuleConstant<Arc<Type>, String>;
|
pub type TypedModuleConstant = ModuleConstant<Arc<Type>>;
|
||||||
pub type UntypedModuleConstant = ModuleConstant<(), ()>;
|
pub type UntypedModuleConstant = ModuleConstant<()>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct ModuleConstant<T, ConstantRecordTag> {
|
pub struct ModuleConstant<T> {
|
||||||
pub doc: Option<String>,
|
pub doc: Option<String>,
|
||||||
pub location: Span,
|
pub location: Span,
|
||||||
pub public: bool,
|
pub public: bool,
|
||||||
pub name: String,
|
pub name: String,
|
||||||
pub annotation: Option<Annotation>,
|
pub annotation: Option<Annotation>,
|
||||||
pub value: Box<Constant<T, ConstantRecordTag>>,
|
pub value: Box<Constant>,
|
||||||
pub tipo: T,
|
pub tipo: T,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -270,11 +270,11 @@ pub struct Validator<T, Expr> {
|
||||||
pub params: Vec<Arg<T>>,
|
pub params: Vec<Arg<T>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TypedDefinition = Definition<Arc<Type>, TypedExpr, String, String>;
|
pub type TypedDefinition = Definition<Arc<Type>, TypedExpr, String>;
|
||||||
pub type UntypedDefinition = Definition<(), UntypedExpr, (), ()>;
|
pub type UntypedDefinition = Definition<(), UntypedExpr, ()>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Definition<T, Expr, ConstantRecordTag, PackageName> {
|
pub enum Definition<T, Expr, PackageName> {
|
||||||
Fn(Function<T, Expr>),
|
Fn(Function<T, Expr>),
|
||||||
|
|
||||||
TypeAlias(TypeAlias<T>),
|
TypeAlias(TypeAlias<T>),
|
||||||
|
@ -283,14 +283,14 @@ pub enum Definition<T, Expr, ConstantRecordTag, PackageName> {
|
||||||
|
|
||||||
Use(Use<PackageName>),
|
Use(Use<PackageName>),
|
||||||
|
|
||||||
ModuleConstant(ModuleConstant<T, ConstantRecordTag>),
|
ModuleConstant(ModuleConstant<T>),
|
||||||
|
|
||||||
Test(Function<T, Expr>),
|
Test(Function<T, Expr>),
|
||||||
|
|
||||||
Validator(Validator<T, Expr>),
|
Validator(Validator<T, Expr>),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B, C, E> Definition<A, B, C, E> {
|
impl<A, B, C> Definition<A, B, C> {
|
||||||
pub fn location(&self) -> Span {
|
pub fn location(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
Definition::Fn(Function { location, .. })
|
Definition::Fn(Function { location, .. })
|
||||||
|
@ -324,91 +324,31 @@ pub struct DefinitionLocation<'module> {
|
||||||
pub span: Span,
|
pub span: Span,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TypedConstant = Constant<Arc<Type>, String>;
|
|
||||||
pub type UntypedConstant = Constant<(), ()>;
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum Constant<T, RecordTag> {
|
pub enum Constant {
|
||||||
Int {
|
Int { location: Span, value: String },
|
||||||
location: Span,
|
|
||||||
value: String,
|
|
||||||
},
|
|
||||||
|
|
||||||
String {
|
String { location: Span, value: String },
|
||||||
location: Span,
|
|
||||||
value: String,
|
|
||||||
},
|
|
||||||
|
|
||||||
Tuple {
|
ByteArray { location: Span, bytes: Vec<u8> },
|
||||||
location: Span,
|
|
||||||
elements: Vec<Self>,
|
|
||||||
},
|
|
||||||
|
|
||||||
List {
|
|
||||||
location: Span,
|
|
||||||
elements: Vec<Self>,
|
|
||||||
tipo: T,
|
|
||||||
},
|
|
||||||
|
|
||||||
Record {
|
|
||||||
location: Span,
|
|
||||||
module: Option<String>,
|
|
||||||
name: String,
|
|
||||||
args: Vec<CallArg<Self>>,
|
|
||||||
tag: RecordTag,
|
|
||||||
tipo: T,
|
|
||||||
field_map: Option<FieldMap>,
|
|
||||||
},
|
|
||||||
|
|
||||||
ByteArray {
|
|
||||||
location: Span,
|
|
||||||
bytes: Vec<u8>,
|
|
||||||
},
|
|
||||||
|
|
||||||
Var {
|
|
||||||
location: Span,
|
|
||||||
module: Option<String>,
|
|
||||||
name: String,
|
|
||||||
constructor: Option<Box<ValueConstructor>>,
|
|
||||||
tipo: T,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl TypedConstant {
|
impl Constant {
|
||||||
pub fn tipo(&self) -> Arc<Type> {
|
pub fn tipo(&self) -> Arc<Type> {
|
||||||
match self {
|
match self {
|
||||||
Constant::Int { .. } => builtins::int(),
|
Constant::Int { .. } => builtins::int(),
|
||||||
Constant::String { .. } => builtins::string(),
|
Constant::String { .. } => builtins::string(),
|
||||||
Constant::ByteArray { .. } => builtins::byte_array(),
|
Constant::ByteArray { .. } => builtins::byte_array(),
|
||||||
Constant::Tuple { elements, .. } => {
|
|
||||||
builtins::tuple(elements.iter().map(|e| e.tipo()).collect())
|
|
||||||
}
|
|
||||||
Constant::List { tipo, .. }
|
|
||||||
| Constant::Record { tipo, .. }
|
|
||||||
| Constant::Var { tipo, .. } => tipo.clone(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl<A, B> Constant<A, B> {
|
|
||||||
pub fn location(&self) -> Span {
|
pub fn location(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
Constant::Int { location, .. }
|
Constant::Int { location, .. }
|
||||||
| Constant::Tuple { location, .. }
|
|
||||||
| Constant::List { location, .. }
|
|
||||||
| Constant::String { location, .. }
|
| Constant::String { location, .. }
|
||||||
| Constant::Record { location, .. }
|
| Constant::ByteArray { location, .. } => *location,
|
||||||
| Constant::ByteArray { location, .. }
|
|
||||||
| Constant::Var { location, .. } => *location,
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_simple(&self) -> bool {
|
|
||||||
matches!(
|
|
||||||
self,
|
|
||||||
Self::Int { .. } | Self::ByteArray { .. } | Self::String { .. }
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type TypedCallArg = CallArg<TypedExpr>;
|
pub type TypedCallArg = CallArg<TypedExpr>;
|
||||||
|
@ -836,15 +776,15 @@ pub type MultiPattern<PatternConstructor, Type> = Vec<Pattern<PatternConstructor
|
||||||
pub type UntypedMultiPattern = MultiPattern<(), ()>;
|
pub type UntypedMultiPattern = MultiPattern<(), ()>;
|
||||||
pub type TypedMultiPattern = MultiPattern<PatternConstructor, Arc<Type>>;
|
pub type TypedMultiPattern = MultiPattern<PatternConstructor, Arc<Type>>;
|
||||||
|
|
||||||
pub type TypedClause = Clause<TypedExpr, PatternConstructor, Arc<Type>, String>;
|
pub type TypedClause = Clause<TypedExpr, PatternConstructor, Arc<Type>>;
|
||||||
pub type UntypedClause = Clause<UntypedExpr, (), (), ()>;
|
pub type UntypedClause = Clause<UntypedExpr, (), ()>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub struct Clause<Expr, PatternConstructor, Type, RecordTag> {
|
pub struct Clause<Expr, PatternConstructor, Type> {
|
||||||
pub location: Span,
|
pub location: Span,
|
||||||
pub pattern: MultiPattern<PatternConstructor, Type>,
|
pub pattern: MultiPattern<PatternConstructor, Type>,
|
||||||
pub alternative_patterns: Vec<MultiPattern<PatternConstructor, Type>>,
|
pub alternative_patterns: Vec<MultiPattern<PatternConstructor, Type>>,
|
||||||
pub guard: Option<ClauseGuard<Type, RecordTag>>,
|
pub guard: Option<ClauseGuard<Type>>,
|
||||||
pub then: Expr,
|
pub then: Expr,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -861,11 +801,11 @@ impl TypedClause {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type UntypedClauseGuard = ClauseGuard<(), ()>;
|
pub type UntypedClauseGuard = ClauseGuard<()>;
|
||||||
pub type TypedClauseGuard = ClauseGuard<Arc<Type>, String>;
|
pub type TypedClauseGuard = ClauseGuard<Arc<Type>>;
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq)]
|
#[derive(Debug, Clone, PartialEq)]
|
||||||
pub enum ClauseGuard<Type, RecordTag> {
|
pub enum ClauseGuard<Type> {
|
||||||
Not {
|
Not {
|
||||||
location: Span,
|
location: Span,
|
||||||
value: Box<Self>,
|
value: Box<Self>,
|
||||||
|
@ -925,10 +865,10 @@ pub enum ClauseGuard<Type, RecordTag> {
|
||||||
name: String,
|
name: String,
|
||||||
},
|
},
|
||||||
|
|
||||||
Constant(Constant<Type, RecordTag>),
|
Constant(Constant),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<A, B> ClauseGuard<A, B> {
|
impl<A> ClauseGuard<A> {
|
||||||
pub fn location(&self) -> Span {
|
pub fn location(&self) -> Span {
|
||||||
match self {
|
match self {
|
||||||
ClauseGuard::Constant(constant) => constant.location(),
|
ClauseGuard::Constant(constant) => constant.location(),
|
||||||
|
|
|
@ -397,8 +397,8 @@ pub fn convert_data_to_type(term: Term<Name>, field_type: &Arc<Type>) -> Term<Na
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rearrange_clauses(
|
pub fn rearrange_clauses(
|
||||||
clauses: Vec<Clause<TypedExpr, PatternConstructor, Arc<Type>, String>>,
|
clauses: Vec<Clause<TypedExpr, PatternConstructor, Arc<Type>>>,
|
||||||
) -> Vec<Clause<TypedExpr, PatternConstructor, Arc<Type>, String>> {
|
) -> Vec<Clause<TypedExpr, PatternConstructor, Arc<Type>>> {
|
||||||
let mut sorted_clauses = clauses;
|
let mut sorted_clauses = clauses;
|
||||||
|
|
||||||
// if we have a list sort clauses so we can plug holes for cases not covered by clauses
|
// if we have a list sort clauses so we can plug holes for cases not covered by clauses
|
||||||
|
@ -1066,11 +1066,7 @@ pub fn check_when_pattern_needs(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn constants_ir(
|
pub fn constants_ir(literal: &Constant, ir_stack: &mut Vec<Air>, scope: Vec<u64>) {
|
||||||
literal: &Constant<Arc<Type>, String>,
|
|
||||||
ir_stack: &mut Vec<Air>,
|
|
||||||
scope: Vec<u64>,
|
|
||||||
) {
|
|
||||||
match literal {
|
match literal {
|
||||||
Constant::Int { value, .. } => {
|
Constant::Int { value, .. } => {
|
||||||
ir_stack.push(Air::Int {
|
ir_stack.push(Air::Int {
|
||||||
|
@ -1084,32 +1080,12 @@ pub fn constants_ir(
|
||||||
value: value.clone(),
|
value: value.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Constant::Tuple { .. } => {
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Constant::List { elements, tipo, .. } => {
|
|
||||||
ir_stack.push(Air::List {
|
|
||||||
scope: scope.clone(),
|
|
||||||
count: elements.len(),
|
|
||||||
tipo: tipo.clone(),
|
|
||||||
tail: false,
|
|
||||||
});
|
|
||||||
|
|
||||||
for element in elements {
|
|
||||||
constants_ir(element, ir_stack, scope.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constant::Record { .. } => {
|
|
||||||
// ir_stack.push(Air::Record { scope, });
|
|
||||||
todo!()
|
|
||||||
}
|
|
||||||
Constant::ByteArray { bytes, .. } => {
|
Constant::ByteArray { bytes, .. } => {
|
||||||
ir_stack.push(Air::ByteArray {
|
ir_stack.push(Air::ByteArray {
|
||||||
scope,
|
scope,
|
||||||
bytes: bytes.clone(),
|
bytes: bytes.clone(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
Constant::Var { .. } => todo!(),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2072,7 +2048,7 @@ pub fn replace_opaque_type(t: &mut Arc<Type>, data_types: IndexMap<DataTypeKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn handle_clause_guard(
|
pub fn handle_clause_guard(
|
||||||
clause_guard: &ClauseGuard<Arc<Type>, String>,
|
clause_guard: &ClauseGuard<Arc<Type>>,
|
||||||
clause_guard_vec: &mut Vec<Air>,
|
clause_guard_vec: &mut Vec<Air>,
|
||||||
scope: Vec<u64>,
|
scope: Vec<u64>,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -103,7 +103,7 @@ pub enum TypedExpr {
|
||||||
location: Span,
|
location: Span,
|
||||||
tipo: Arc<Type>,
|
tipo: Arc<Type>,
|
||||||
subjects: Vec<Self>,
|
subjects: Vec<Self>,
|
||||||
clauses: Vec<Clause<Self, PatternConstructor, Arc<Type>, String>>,
|
clauses: Vec<Clause<Self, PatternConstructor, Arc<Type>>>,
|
||||||
},
|
},
|
||||||
|
|
||||||
If {
|
If {
|
||||||
|
@ -390,7 +390,7 @@ pub enum UntypedExpr {
|
||||||
When {
|
When {
|
||||||
location: Span,
|
location: Span,
|
||||||
subjects: Vec<Self>,
|
subjects: Vec<Self>,
|
||||||
clauses: Vec<Clause<Self, (), (), ()>>,
|
clauses: Vec<Clause<Self, (), ()>>,
|
||||||
},
|
},
|
||||||
|
|
||||||
If {
|
If {
|
||||||
|
|
|
@ -7,10 +7,10 @@ use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
Annotation, Arg, ArgName, AssignmentKind, BinOp, CallArg, ClauseGuard, Constant, DataType,
|
Annotation, Arg, ArgName, AssignmentKind, BinOp, CallArg, ClauseGuard, Constant, DataType,
|
||||||
Definition, Function, IfBranch, ModuleConstant, Pattern, RecordConstructor,
|
Definition, Function, IfBranch, ModuleConstant, Pattern, RecordConstructor,
|
||||||
RecordConstructorArg, RecordUpdateSpread, Span, TraceKind, TypeAlias, TypedArg,
|
RecordConstructorArg, RecordUpdateSpread, Span, TraceKind, TypeAlias, TypedArg, UnOp,
|
||||||
TypedConstant, UnOp, UnqualifiedImport, UntypedArg, UntypedClause, UntypedClauseGuard,
|
UnqualifiedImport, UntypedArg, UntypedClause, UntypedClauseGuard, UntypedDefinition,
|
||||||
UntypedDefinition, UntypedFunction, UntypedModule, UntypedPattern, UntypedRecordUpdateArg,
|
UntypedFunction, UntypedModule, UntypedPattern, UntypedRecordUpdateArg, Use, Validator,
|
||||||
Use, Validator, CAPTURE_VARIABLE,
|
CAPTURE_VARIABLE,
|
||||||
},
|
},
|
||||||
docvec,
|
docvec,
|
||||||
expr::{UntypedExpr, DEFAULT_ERROR_STR, DEFAULT_TODO_STR},
|
expr::{UntypedExpr, DEFAULT_ERROR_STR, DEFAULT_TODO_STR},
|
||||||
|
@ -324,82 +324,15 @@ impl<'comments> Formatter<'comments> {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn const_expr<'a, A, B>(&mut self, value: &'a Constant<A, B>) -> Document<'a> {
|
fn const_expr<'a>(&mut self, value: &'a Constant) -> Document<'a> {
|
||||||
match value {
|
match value {
|
||||||
Constant::ByteArray { bytes, .. } => self.bytearray(bytes),
|
Constant::ByteArray { bytes, .. } => self.bytearray(bytes),
|
||||||
Constant::Int { value, .. } => value.to_doc(),
|
Constant::Int { value, .. } => value.to_doc(),
|
||||||
|
|
||||||
Constant::String { value, .. } => self.string(value),
|
Constant::String { value, .. } => self.string(value),
|
||||||
|
|
||||||
Constant::List { elements, .. } => {
|
|
||||||
let comma: fn() -> Document<'a> = if elements.iter().all(Constant::is_simple) {
|
|
||||||
|| flex_break(",", ", ")
|
|
||||||
} else {
|
|
||||||
|| break_(",", ", ")
|
|
||||||
};
|
|
||||||
let elements_document = join(elements.iter().map(|e| self.const_expr(e)), comma());
|
|
||||||
list(elements_document, elements.len(), None)
|
|
||||||
}
|
|
||||||
|
|
||||||
Constant::Record {
|
|
||||||
name,
|
|
||||||
args,
|
|
||||||
module: None,
|
|
||||||
..
|
|
||||||
} if args.is_empty() => name.to_doc(),
|
|
||||||
|
|
||||||
Constant::Record {
|
|
||||||
name,
|
|
||||||
args,
|
|
||||||
module: Some(m),
|
|
||||||
..
|
|
||||||
} if args.is_empty() => m.to_doc().append(".").append(name.as_str()),
|
|
||||||
|
|
||||||
Constant::Record {
|
|
||||||
name,
|
|
||||||
args,
|
|
||||||
module: None,
|
|
||||||
..
|
|
||||||
} => name
|
|
||||||
.to_doc()
|
|
||||||
.append(wrap_args(
|
|
||||||
args.iter()
|
|
||||||
.map(|a| (self.constant_call_arg(a), a.label.is_some())),
|
|
||||||
))
|
|
||||||
.group(),
|
|
||||||
|
|
||||||
Constant::Record {
|
|
||||||
name,
|
|
||||||
args,
|
|
||||||
module: Some(m),
|
|
||||||
..
|
|
||||||
} => m
|
|
||||||
.to_doc()
|
|
||||||
.append(".")
|
|
||||||
.append(name.as_str())
|
|
||||||
.append(wrap_args(
|
|
||||||
args.iter()
|
|
||||||
.map(|a| (self.constant_call_arg(a), a.label.is_some())),
|
|
||||||
))
|
|
||||||
.group(),
|
|
||||||
|
|
||||||
Constant::Var {
|
|
||||||
name, module: None, ..
|
|
||||||
} => name.to_doc(),
|
|
||||||
|
|
||||||
Constant::Var {
|
|
||||||
name,
|
|
||||||
module: Some(module),
|
|
||||||
..
|
|
||||||
} => docvec![module, ".", name],
|
|
||||||
|
|
||||||
Constant::Tuple { elements, .. } => {
|
|
||||||
wrap_args(elements.iter().map(|e| (self.const_expr(e), false))).group()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn docs_const_expr<'a>(&mut self, name: &'a str, value: &'a TypedConstant) -> Document<'a> {
|
pub fn docs_const_expr<'a>(&mut self, name: &'a str, value: &'a Constant) -> Document<'a> {
|
||||||
let mut printer = tipo::pretty::Printer::new();
|
let mut printer = tipo::pretty::Printer::new();
|
||||||
name.to_doc()
|
name.to_doc()
|
||||||
.append(": ")
|
.append(": ")
|
||||||
|
@ -1631,13 +1564,6 @@ impl<'comments> Formatter<'comments> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn constant_call_arg<'a, A, B>(&mut self, arg: &'a CallArg<Constant<A, B>>) -> Document<'a> {
|
|
||||||
match &arg.label {
|
|
||||||
None => self.const_expr(&arg.value),
|
|
||||||
Some(s) => s.to_doc().append(": ").append(self.const_expr(&arg.value)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn un_op<'a>(&mut self, value: &'a UntypedExpr, op: &'a UnOp) -> Document<'a> {
|
fn un_op<'a>(&mut self, value: &'a UntypedExpr, op: &'a UnOp) -> Document<'a> {
|
||||||
match op {
|
match op {
|
||||||
UnOp::Not => docvec!["!", self.wrap_unary_op(value)],
|
UnOp::Not => docvec!["!", self.wrap_unary_op(value)],
|
||||||
|
|
|
@ -386,162 +386,32 @@ fn constant_parser() -> impl Parser<Token, ast::UntypedDefinition, Error = Parse
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn constant_value_parser() -> impl Parser<Token, ast::UntypedConstant, Error = ParseError> {
|
fn constant_value_parser() -> impl Parser<Token, ast::Constant, Error = ParseError> {
|
||||||
recursive(|r| {
|
let constant_string_parser =
|
||||||
let constant_string_parser =
|
select! {Token::String {value} => value}.map_with_span(|value, span| {
|
||||||
select! {Token::String {value} => value}.map_with_span(|value, span| {
|
ast::Constant::String {
|
||||||
ast::UntypedConstant::String {
|
|
||||||
location: span,
|
|
||||||
value,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let constant_int_parser =
|
|
||||||
select! {Token::Int {value} => value}.map_with_span(|value, span| {
|
|
||||||
ast::UntypedConstant::Int {
|
|
||||||
location: span,
|
|
||||||
value,
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let constant_tuple_parser = r
|
|
||||||
.clone()
|
|
||||||
.separated_by(just(Token::Comma))
|
|
||||||
.at_least(2)
|
|
||||||
.allow_trailing()
|
|
||||||
.delimited_by(
|
|
||||||
choice((just(Token::LeftParen), just(Token::NewLineLeftParen))),
|
|
||||||
just(Token::RightParen),
|
|
||||||
)
|
|
||||||
.map_with_span(|elements, span| ast::UntypedConstant::Tuple {
|
|
||||||
location: span,
|
location: span,
|
||||||
elements,
|
value,
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
let constant_bytearray_parser =
|
let constant_int_parser =
|
||||||
bytearray_parser().map_with_span(|bytes, span| ast::UntypedConstant::ByteArray {
|
select! {Token::Int {value} => value}.map_with_span(|value, span| ast::Constant::Int {
|
||||||
location: span,
|
location: span,
|
||||||
bytes,
|
value,
|
||||||
});
|
});
|
||||||
|
|
||||||
let constant_list_parser = r
|
let constant_bytearray_parser =
|
||||||
.clone()
|
bytearray_parser().map_with_span(|bytes, span| ast::Constant::ByteArray {
|
||||||
.separated_by(just(Token::Comma))
|
location: span,
|
||||||
.allow_trailing()
|
bytes,
|
||||||
.delimited_by(just(Token::LeftSquare), just(Token::RightSquare))
|
});
|
||||||
.map_with_span(|elements, span| ast::UntypedConstant::List {
|
|
||||||
location: span,
|
|
||||||
elements,
|
|
||||||
tipo: (),
|
|
||||||
});
|
|
||||||
|
|
||||||
let constant_record_parser = choice((
|
choice((
|
||||||
choice((
|
constant_string_parser,
|
||||||
select! {Token::Name { name } => name}
|
constant_int_parser,
|
||||||
.then_ignore(just(Token::Dot))
|
constant_bytearray_parser,
|
||||||
.or_not()
|
))
|
||||||
.then(select! {Token::UpName { name } => name})
|
|
||||||
.then(
|
|
||||||
select! {Token::Name {name} => name}
|
|
||||||
.then_ignore(just(Token::Colon))
|
|
||||||
.or_not()
|
|
||||||
.then(r.clone())
|
|
||||||
.validate(|(label_opt, value), span, emit| {
|
|
||||||
let label = if label_opt.is_some() {
|
|
||||||
label_opt
|
|
||||||
} else if let ast::UntypedConstant::Var { name, .. } = &value {
|
|
||||||
Some(name.clone())
|
|
||||||
} else {
|
|
||||||
emit(ParseError::expected_input_found(
|
|
||||||
value.location(),
|
|
||||||
None,
|
|
||||||
Some(error::Pattern::RecordPunning),
|
|
||||||
));
|
|
||||||
|
|
||||||
None
|
|
||||||
};
|
|
||||||
|
|
||||||
ast::CallArg {
|
|
||||||
location: span,
|
|
||||||
value,
|
|
||||||
label,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.separated_by(just(Token::Comma))
|
|
||||||
.allow_trailing()
|
|
||||||
.delimited_by(just(Token::LeftBrace), just(Token::RightBrace)),
|
|
||||||
)
|
|
||||||
.map_with_span(
|
|
||||||
|((module, name), args), span| ast::UntypedConstant::Record {
|
|
||||||
location: span,
|
|
||||||
module,
|
|
||||||
name,
|
|
||||||
args,
|
|
||||||
tag: (),
|
|
||||||
tipo: (),
|
|
||||||
field_map: None,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
select! {Token::Name { name } => name}
|
|
||||||
.then_ignore(just(Token::Dot))
|
|
||||||
.or_not()
|
|
||||||
.then(select! {Token::UpName { name } => name})
|
|
||||||
.then(
|
|
||||||
r.clone()
|
|
||||||
.map_with_span(|value, span| ast::CallArg {
|
|
||||||
location: span,
|
|
||||||
value,
|
|
||||||
label: None,
|
|
||||||
})
|
|
||||||
.separated_by(just(Token::Comma))
|
|
||||||
.allow_trailing()
|
|
||||||
.delimited_by(just(Token::LeftParen), just(Token::RightParen)),
|
|
||||||
)
|
|
||||||
.map_with_span(
|
|
||||||
|((module, name), args), span| ast::UntypedConstant::Record {
|
|
||||||
location: span,
|
|
||||||
module,
|
|
||||||
name,
|
|
||||||
args,
|
|
||||||
tag: (),
|
|
||||||
tipo: (),
|
|
||||||
field_map: None,
|
|
||||||
},
|
|
||||||
),
|
|
||||||
)),
|
|
||||||
select! {Token::Name { name } => name}
|
|
||||||
.then_ignore(just(Token::Dot))
|
|
||||||
.then(select! {Token::Name{name} => name})
|
|
||||||
.map_with_span(|(module, name), span: Span| ast::UntypedConstant::Var {
|
|
||||||
location: span.union(span),
|
|
||||||
module: Some(module),
|
|
||||||
name,
|
|
||||||
constructor: None,
|
|
||||||
tipo: (),
|
|
||||||
}),
|
|
||||||
));
|
|
||||||
|
|
||||||
let constant_var_parser =
|
|
||||||
select! {Token::Name {name} => name}.map_with_span(|name, span| {
|
|
||||||
ast::UntypedConstant::Var {
|
|
||||||
location: span,
|
|
||||||
module: None,
|
|
||||||
name,
|
|
||||||
constructor: None,
|
|
||||||
tipo: (),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
choice((
|
|
||||||
constant_string_parser,
|
|
||||||
constant_int_parser,
|
|
||||||
constant_bytearray_parser,
|
|
||||||
constant_tuple_parser,
|
|
||||||
constant_list_parser,
|
|
||||||
constant_record_parser,
|
|
||||||
constant_var_parser,
|
|
||||||
))
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bytearray_parser() -> impl Parser<Token, Vec<u8>, Error = ParseError> {
|
pub fn bytearray_parser() -> impl Parser<Token, Vec<u8>, Error = ParseError> {
|
||||||
|
@ -1407,8 +1277,7 @@ pub fn expr_parser(
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn when_clause_guard_parser() -> impl Parser<Token, ast::ClauseGuard<(), ()>, Error = ParseError>
|
pub fn when_clause_guard_parser() -> impl Parser<Token, ast::ClauseGuard<()>, Error = ParseError> {
|
||||||
{
|
|
||||||
recursive(|r| {
|
recursive(|r| {
|
||||||
let var_parser = select! {
|
let var_parser = select! {
|
||||||
Token::Name { name } => name,
|
Token::Name { name } => name,
|
||||||
|
|
|
@ -3,7 +3,7 @@ use std::{cell::RefCell, collections::HashMap, ops::Deref, sync::Arc};
|
||||||
use uplc::{ast::Type as UplcType, builtins::DefaultFunction};
|
use uplc::{ast::Type as UplcType, builtins::DefaultFunction};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
ast::{Constant, DefinitionLocation, ModuleKind, Span, TypedConstant},
|
ast::{Constant, DefinitionLocation, ModuleKind, Span},
|
||||||
tipo::fields::FieldMap,
|
tipo::fields::FieldMap,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -584,7 +584,7 @@ pub enum ValueConstructorVariant {
|
||||||
ModuleConstant {
|
ModuleConstant {
|
||||||
location: Span,
|
location: Span,
|
||||||
module: String,
|
module: String,
|
||||||
literal: Constant<Arc<Type>, String>,
|
literal: Constant,
|
||||||
},
|
},
|
||||||
|
|
||||||
/// A function belonging to the module
|
/// A function belonging to the module
|
||||||
|
@ -744,7 +744,7 @@ pub enum ModuleValueConstructor {
|
||||||
},
|
},
|
||||||
|
|
||||||
Constant {
|
Constant {
|
||||||
literal: TypedConstant,
|
literal: Constant,
|
||||||
location: Span,
|
location: Span,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ use crate::{
|
||||||
ast::{
|
ast::{
|
||||||
Annotation, Arg, ArgName, AssignmentKind, BinOp, CallArg, Clause, ClauseGuard, Constant,
|
Annotation, Arg, ArgName, AssignmentKind, BinOp, CallArg, Clause, ClauseGuard, Constant,
|
||||||
IfBranch, RecordUpdateSpread, Span, TraceKind, Tracing, TypedArg, TypedCallArg,
|
IfBranch, RecordUpdateSpread, Span, TraceKind, Tracing, TypedArg, TypedCallArg,
|
||||||
TypedClause, TypedClauseGuard, TypedConstant, TypedIfBranch, TypedMultiPattern,
|
TypedClause, TypedClauseGuard, TypedIfBranch, TypedMultiPattern, TypedRecordUpdateArg,
|
||||||
TypedRecordUpdateArg, UnOp, UntypedArg, UntypedClause, UntypedClauseGuard, UntypedConstant,
|
UnOp, UntypedArg, UntypedClause, UntypedClauseGuard, UntypedIfBranch, UntypedMultiPattern,
|
||||||
UntypedIfBranch, UntypedMultiPattern, UntypedPattern, UntypedRecordUpdateArg,
|
UntypedPattern, UntypedRecordUpdateArg,
|
||||||
},
|
},
|
||||||
builtins::{bool, byte_array, function, int, list, string, tuple},
|
builtins::{bool, byte_array, function, int, list, string, tuple},
|
||||||
expr::{TypedExpr, UntypedExpr},
|
expr::{TypedExpr, UntypedExpr},
|
||||||
|
@ -22,8 +22,7 @@ use super::{
|
||||||
hydrator::Hydrator,
|
hydrator::Hydrator,
|
||||||
pattern::PatternTyper,
|
pattern::PatternTyper,
|
||||||
pipe::PipeTyper,
|
pipe::PipeTyper,
|
||||||
ModuleValueConstructor, PatternConstructor, RecordAccessor, Type, ValueConstructor,
|
PatternConstructor, RecordAccessor, Type, ValueConstructor, ValueConstructorVariant,
|
||||||
ValueConstructorVariant,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -48,7 +47,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
&mut self,
|
&mut self,
|
||||||
subjects_count: usize,
|
subjects_count: usize,
|
||||||
subjects: &[Arc<Type>],
|
subjects: &[Arc<Type>],
|
||||||
typed_clauses: &[Clause<TypedExpr, PatternConstructor, Arc<Type>, String>],
|
typed_clauses: &[Clause<TypedExpr, PatternConstructor, Arc<Type>>],
|
||||||
location: Span,
|
location: Span,
|
||||||
) -> Result<(), Vec<String>> {
|
) -> Result<(), Vec<String>> {
|
||||||
// Because exhaustiveness checking in presence of multiple subjects is similar
|
// Because exhaustiveness checking in presence of multiple subjects is similar
|
||||||
|
@ -1338,29 +1337,13 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
Ok((typed_pattern, typed_alternatives))
|
Ok((typed_pattern, typed_alternatives))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer_const_tuple(
|
|
||||||
&mut self,
|
|
||||||
untyped_elements: Vec<UntypedConstant>,
|
|
||||||
location: Span,
|
|
||||||
) -> Result<TypedConstant, Error> {
|
|
||||||
let mut elements = Vec::with_capacity(untyped_elements.len());
|
|
||||||
|
|
||||||
for element in untyped_elements {
|
|
||||||
let element = self.infer_const(&None, element)?;
|
|
||||||
|
|
||||||
elements.push(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Constant::Tuple { elements, location })
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: extract the type annotation checking into a infer_module_const
|
// TODO: extract the type annotation checking into a infer_module_const
|
||||||
// function that uses this function internally
|
// function that uses this function internally
|
||||||
pub fn infer_const(
|
pub fn infer_const(
|
||||||
&mut self,
|
&mut self,
|
||||||
annotation: &Option<Annotation>,
|
annotation: &Option<Annotation>,
|
||||||
value: UntypedConstant,
|
value: Constant,
|
||||||
) -> Result<TypedConstant, Error> {
|
) -> Result<Constant, Error> {
|
||||||
let inferred = match value {
|
let inferred = match value {
|
||||||
Constant::Int {
|
Constant::Int {
|
||||||
location, value, ..
|
location, value, ..
|
||||||
|
@ -1370,216 +1353,7 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
location, value, ..
|
location, value, ..
|
||||||
} => Ok(Constant::String { location, value }),
|
} => Ok(Constant::String { location, value }),
|
||||||
|
|
||||||
Constant::Tuple {
|
|
||||||
elements, location, ..
|
|
||||||
} => self.infer_const_tuple(elements, location),
|
|
||||||
|
|
||||||
Constant::List {
|
|
||||||
elements, location, ..
|
|
||||||
} => self.infer_const_list(elements, location),
|
|
||||||
|
|
||||||
Constant::ByteArray { location, bytes } => Ok(Constant::ByteArray { location, bytes }),
|
Constant::ByteArray { location, bytes } => Ok(Constant::ByteArray { location, bytes }),
|
||||||
|
|
||||||
Constant::Record {
|
|
||||||
module,
|
|
||||||
location,
|
|
||||||
name,
|
|
||||||
args,
|
|
||||||
// field_map, is always None here because untyped not yet unified
|
|
||||||
..
|
|
||||||
} if args.is_empty() => {
|
|
||||||
// Register the module as having been used if it was imported
|
|
||||||
if let Some(ref module) = &module {
|
|
||||||
self.environment.unused_modules.remove(module);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Type check the record constructor
|
|
||||||
let constructor = self.infer_value_constructor(&module, &name, &location)?;
|
|
||||||
|
|
||||||
let (tag, field_map) = match &constructor.variant {
|
|
||||||
ValueConstructorVariant::Record {
|
|
||||||
name, field_map, ..
|
|
||||||
} => (name.clone(), field_map.clone()),
|
|
||||||
|
|
||||||
ValueConstructorVariant::ModuleFn { .. }
|
|
||||||
| ValueConstructorVariant::LocalVariable { .. } => {
|
|
||||||
return Err(Error::NonLocalClauseGuardVariable { location, name })
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove this clone. Could use an rc instead
|
|
||||||
ValueConstructorVariant::ModuleConstant { literal, .. } => {
|
|
||||||
return Ok(literal.clone())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(Constant::Record {
|
|
||||||
module,
|
|
||||||
location,
|
|
||||||
name,
|
|
||||||
args: vec![],
|
|
||||||
tipo: constructor.tipo,
|
|
||||||
tag,
|
|
||||||
field_map,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
Constant::Record {
|
|
||||||
module,
|
|
||||||
location,
|
|
||||||
name,
|
|
||||||
mut args,
|
|
||||||
// field_map, is always None here because untyped not yet unified
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
// Register the module as having been used if it was imported
|
|
||||||
if let Some(ref module) = &module {
|
|
||||||
self.environment.unused_modules.remove(module);
|
|
||||||
}
|
|
||||||
|
|
||||||
let constructor = self.infer_value_constructor(&module, &name, &location)?;
|
|
||||||
|
|
||||||
let (tag, field_map) = match &constructor.variant {
|
|
||||||
ValueConstructorVariant::Record {
|
|
||||||
name, field_map, ..
|
|
||||||
} => (name.clone(), field_map.clone()),
|
|
||||||
|
|
||||||
ValueConstructorVariant::ModuleFn { .. }
|
|
||||||
| ValueConstructorVariant::LocalVariable { .. } => {
|
|
||||||
return Err(Error::NonLocalClauseGuardVariable { location, name })
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: remove this clone. Could be an rc instead
|
|
||||||
ValueConstructorVariant::ModuleConstant { literal, .. } => {
|
|
||||||
return Ok(literal.clone())
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Pretty much all the other infer functions operate on UntypedExpr
|
|
||||||
// or TypedExpr rather than ClauseGuard. To make things easier we
|
|
||||||
// build the TypedExpr equivalent of the constructor and use that
|
|
||||||
// TODO: resvisit this. It is rather awkward at present how we
|
|
||||||
// have to convert to this other data structure.
|
|
||||||
let fun = match &module {
|
|
||||||
Some(module_name) => {
|
|
||||||
let tipo = Arc::clone(&constructor.tipo);
|
|
||||||
|
|
||||||
let module_name = self
|
|
||||||
.environment
|
|
||||||
.imported_modules
|
|
||||||
.get(module_name)
|
|
||||||
.expect("Failed to find previously located module import")
|
|
||||||
.1
|
|
||||||
.name
|
|
||||||
.clone();
|
|
||||||
|
|
||||||
let module_value_constructor = ModuleValueConstructor::Record {
|
|
||||||
name: name.clone(),
|
|
||||||
field_map: field_map.clone(),
|
|
||||||
arity: args.len(),
|
|
||||||
tipo: Arc::clone(&tipo),
|
|
||||||
location: constructor.variant.location(),
|
|
||||||
};
|
|
||||||
|
|
||||||
TypedExpr::ModuleSelect {
|
|
||||||
label: name.clone(),
|
|
||||||
module_alias: module_name.clone(),
|
|
||||||
module_name,
|
|
||||||
tipo,
|
|
||||||
constructor: module_value_constructor,
|
|
||||||
location,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
None => TypedExpr::Var {
|
|
||||||
constructor,
|
|
||||||
location,
|
|
||||||
name: name.clone(),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
// This is basically the same code as do_infer_call_with_known_fun()
|
|
||||||
// except the args are typed with infer_clause_guard() here.
|
|
||||||
// This duplication is a bit awkward but it works!
|
|
||||||
// Potentially this could be improved later
|
|
||||||
match self.get_field_map(&fun, location)? {
|
|
||||||
// The fun has a field map so labelled arguments may be present and need to be reordered.
|
|
||||||
Some(field_map) => field_map.reorder(&mut args, location)?,
|
|
||||||
|
|
||||||
// The fun has no field map and so we error if arguments have been labelled
|
|
||||||
None => assert_no_labeled_arguments(&args)
|
|
||||||
.map(|(location, label)| {
|
|
||||||
Err(Error::UnexpectedLabeledArg { location, label })
|
|
||||||
})
|
|
||||||
.unwrap_or(Ok(()))?,
|
|
||||||
}
|
|
||||||
|
|
||||||
let (mut args_types, return_type) = self.environment.match_fun_type(
|
|
||||||
fun.tipo(),
|
|
||||||
args.len(),
|
|
||||||
fun.location(),
|
|
||||||
location,
|
|
||||||
)?;
|
|
||||||
|
|
||||||
let mut typed_args = Vec::new();
|
|
||||||
|
|
||||||
for (tipo, arg) in args_types.iter_mut().zip(args) {
|
|
||||||
let CallArg {
|
|
||||||
label,
|
|
||||||
value,
|
|
||||||
location,
|
|
||||||
} = arg;
|
|
||||||
|
|
||||||
let value = self.infer_const(&None, value)?;
|
|
||||||
|
|
||||||
self.unify(tipo.clone(), value.tipo(), value.location(), tipo.is_data())?;
|
|
||||||
|
|
||||||
typed_args.push(CallArg {
|
|
||||||
label,
|
|
||||||
value,
|
|
||||||
location,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Constant::Record {
|
|
||||||
module,
|
|
||||||
location,
|
|
||||||
name,
|
|
||||||
args: typed_args,
|
|
||||||
tipo: return_type,
|
|
||||||
tag,
|
|
||||||
field_map,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
Constant::Var {
|
|
||||||
location,
|
|
||||||
module,
|
|
||||||
name,
|
|
||||||
..
|
|
||||||
} => {
|
|
||||||
// Register the module as having been used if it was imported
|
|
||||||
if let Some(ref module) = &module {
|
|
||||||
self.environment.unused_modules.remove(module);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Infer the type of this constant
|
|
||||||
let constructor = self.infer_value_constructor(&module, &name, &location)?;
|
|
||||||
|
|
||||||
match constructor.variant {
|
|
||||||
ValueConstructorVariant::ModuleConstant { .. }
|
|
||||||
| ValueConstructorVariant::ModuleFn { .. } => Ok(Constant::Var {
|
|
||||||
location,
|
|
||||||
module,
|
|
||||||
name,
|
|
||||||
tipo: Arc::clone(&constructor.tipo),
|
|
||||||
constructor: Some(Box::from(constructor)),
|
|
||||||
}),
|
|
||||||
// constructor.variant cannot be a LocalVariable because module constants can
|
|
||||||
// only be defined at module scope. It also cannot be a Record because then
|
|
||||||
// this constant would have been parsed as a Constant::Record. Therefore this
|
|
||||||
// code is unreachable.
|
|
||||||
_ => unreachable!(),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}?;
|
}?;
|
||||||
|
|
||||||
// Check type annotation is accurate.
|
// Check type annotation is accurate.
|
||||||
|
@ -1597,30 +1371,6 @@ impl<'a, 'b> ExprTyper<'a, 'b> {
|
||||||
Ok(inferred)
|
Ok(inferred)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn infer_const_list(
|
|
||||||
&mut self,
|
|
||||||
untyped_elements: Vec<UntypedConstant>,
|
|
||||||
location: Span,
|
|
||||||
) -> Result<TypedConstant, Error> {
|
|
||||||
let tipo = self.new_unbound_var();
|
|
||||||
|
|
||||||
let mut elements = Vec::with_capacity(untyped_elements.len());
|
|
||||||
|
|
||||||
for element in untyped_elements {
|
|
||||||
let element = self.infer_const(&None, element)?;
|
|
||||||
|
|
||||||
self.unify(tipo.clone(), element.tipo(), element.location(), false)?;
|
|
||||||
|
|
||||||
elements.push(element);
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Constant::List {
|
|
||||||
elements,
|
|
||||||
location,
|
|
||||||
tipo: list(tipo),
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn infer_if(
|
fn infer_if(
|
||||||
&mut self,
|
&mut self,
|
||||||
branches: Vec1<UntypedIfBranch>,
|
branches: Vec1<UntypedIfBranch>,
|
||||||
|
|
|
@ -689,7 +689,7 @@ impl<'a> CodeGenerator<'a> {
|
||||||
&mut self,
|
&mut self,
|
||||||
ir_stack: &mut Vec<Air>,
|
ir_stack: &mut Vec<Air>,
|
||||||
clause_properties: &mut ClauseProperties,
|
clause_properties: &mut ClauseProperties,
|
||||||
clauses: &[Clause<TypedExpr, PatternConstructor, Arc<Type>, String>],
|
clauses: &[Clause<TypedExpr, PatternConstructor, Arc<Type>>],
|
||||||
subject_type: &Arc<Type>,
|
subject_type: &Arc<Type>,
|
||||||
scope: Vec<u64>,
|
scope: Vec<u64>,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -1,15 +1,17 @@
|
||||||
type Foo {
|
const int_constant = 42
|
||||||
foo: Int,
|
|
||||||
|
test int() {
|
||||||
|
int_constant == 42
|
||||||
}
|
}
|
||||||
|
|
||||||
const foo_constant = Foo { foo: 42 }
|
const bytearray_constant = #"abcd"
|
||||||
|
|
||||||
test foo() {
|
test bytearray() {
|
||||||
foo_constant == Foo { foo: 42 }
|
bytearray_constant == #"abcd"
|
||||||
}
|
}
|
||||||
|
|
||||||
const tuple_constant = (1, 2, 3)
|
const string_constant = "FOO"
|
||||||
|
|
||||||
test bar() {
|
test string() {
|
||||||
tuple_constant == (1, 2, 3)
|
string_constant == "FOO"
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue