Merge pull request #390 from aiken-lang/acceptance-test-060--record-and-tuple-constants
Remove complex constants.
This commit is contained in:
commit
1aea586cab
|
@ -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::UntypedConstant::String {
|
ast::Constant::String {
|
||||||
location: span,
|
location: span,
|
||||||
value,
|
value,
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
let constant_int_parser =
|
let constant_int_parser =
|
||||||
select! {Token::Int {value} => value}.map_with_span(|value, span| {
|
select! {Token::Int {value} => value}.map_with_span(|value, span| ast::Constant::Int {
|
||||||
ast::UntypedConstant::Int {
|
|
||||||
location: span,
|
location: span,
|
||||||
value,
|
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,
|
|
||||||
elements,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
let constant_bytearray_parser =
|
let constant_bytearray_parser =
|
||||||
bytearray_parser().map_with_span(|bytes, span| ast::UntypedConstant::ByteArray {
|
bytearray_parser().map_with_span(|bytes, span| ast::Constant::ByteArray {
|
||||||
location: span,
|
location: span,
|
||||||
bytes,
|
bytes,
|
||||||
});
|
});
|
||||||
|
|
||||||
let constant_list_parser = r
|
|
||||||
.clone()
|
|
||||||
.separated_by(just(Token::Comma))
|
|
||||||
.allow_trailing()
|
|
||||||
.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((
|
|
||||||
select! {Token::Name { name } => name}
|
|
||||||
.then_ignore(just(Token::Dot))
|
|
||||||
.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((
|
choice((
|
||||||
constant_string_parser,
|
constant_string_parser,
|
||||||
constant_int_parser,
|
constant_int_parser,
|
||||||
constant_bytearray_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>,
|
||||||
) {
|
) {
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
# This file was generated by Aiken
|
||||||
|
# You typically do not need to edit this file
|
||||||
|
|
||||||
|
requirements = []
|
||||||
|
packages = []
|
|
@ -0,0 +1,2 @@
|
||||||
|
name = "aiken-lang/acceptance_test_060"
|
||||||
|
version = "0.0.0"
|
|
@ -0,0 +1,17 @@
|
||||||
|
const int_constant = 42
|
||||||
|
|
||||||
|
test int() {
|
||||||
|
int_constant == 42
|
||||||
|
}
|
||||||
|
|
||||||
|
const bytearray_constant = #"abcd"
|
||||||
|
|
||||||
|
test bytearray() {
|
||||||
|
bytearray_constant == #"abcd"
|
||||||
|
}
|
||||||
|
|
||||||
|
const string_constant = "FOO"
|
||||||
|
|
||||||
|
test string() {
|
||||||
|
string_constant == "FOO"
|
||||||
|
}
|
Loading…
Reference in New Issue