Compare commits
7 Commits
cbdd247c5c
...
354dd7d8c1
Author | SHA1 | Date | |
---|---|---|---|
|
354dd7d8c1 | ||
|
71911f0ab5 | ||
|
d6c5cd100b | ||
|
88dfa87e85 | ||
|
89a93d59c7 | ||
|
0eccceabd9 | ||
|
9d9331f4b0 |
@ -616,8 +616,8 @@ fn primary_expr_no_struct(input: Span) -> ParseResult<ExpressionKind> {
|
|||||||
bool_literal,
|
bool_literal,
|
||||||
float_literal,
|
float_literal,
|
||||||
number_literal,
|
number_literal,
|
||||||
string_literal,
|
|
||||||
self_expr,
|
self_expr,
|
||||||
|
string_literal,
|
||||||
)),
|
)),
|
||||||
)(input)
|
)(input)
|
||||||
}
|
}
|
||||||
|
@ -339,7 +339,7 @@ impl<'a, 'b> Reducer<'a, 'b> {
|
|||||||
|
|
||||||
match symbol.spec() {
|
match symbol.spec() {
|
||||||
Builtin(b) => Expression::Callable(Callable::Builtin(b)),
|
Builtin(b) => Expression::Callable(Callable::Builtin(b)),
|
||||||
Func => Expression::Lookup(Lookup::Function(def_id.unwrap())),
|
Func { .. } => Expression::Lookup(Lookup::Function(def_id.unwrap())),
|
||||||
GlobalBinding => Expression::Lookup(Lookup::GlobalVar(def_id.unwrap())),
|
GlobalBinding => Expression::Lookup(Lookup::GlobalVar(def_id.unwrap())),
|
||||||
LocalVariable => Expression::Lookup(Lookup::LocalVar(def_id.unwrap())),
|
LocalVariable => Expression::Lookup(Lookup::LocalVar(def_id.unwrap())),
|
||||||
FunctionParam(n) => Expression::Lookup(Lookup::Param(n)),
|
FunctionParam(n) => Expression::Lookup(Lookup::Param(n)),
|
||||||
|
@ -17,6 +17,12 @@ impl Fqsn {
|
|||||||
Fqsn { scopes: v }
|
Fqsn { scopes: v }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn extend(&self, new_item: &str) -> Self {
|
||||||
|
let mut new = self.clone();
|
||||||
|
new.scopes.push(ScopeSegment::Name(Rc::new(new_item.to_string())));
|
||||||
|
new
|
||||||
|
}
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
pub fn from_strs(strs: &[&str]) -> Fqsn {
|
pub fn from_strs(strs: &[&str]) -> Fqsn {
|
||||||
let mut scopes = vec![];
|
let mut scopes = vec![];
|
||||||
|
@ -32,7 +32,7 @@ pub type DefId = Id<DefItem>;
|
|||||||
pub enum SymbolError {
|
pub enum SymbolError {
|
||||||
DuplicateName { prev_name: Fqsn, location: Location },
|
DuplicateName { prev_name: Fqsn, location: Location },
|
||||||
DuplicateVariant { type_fqsn: Fqsn, name: String },
|
DuplicateVariant { type_fqsn: Fqsn, name: String },
|
||||||
DuplicateRecord { type_name: Fqsn, location: Location, member: String },
|
DuplicateRecord { type_fqsn: Fqsn, location: Location, record: String, member: String },
|
||||||
UnknownAnnotation { name: String },
|
UnknownAnnotation { name: String },
|
||||||
BadAnnotation { name: String, msg: String },
|
BadAnnotation { name: String, msg: String },
|
||||||
}
|
}
|
||||||
@ -52,7 +52,10 @@ enum NameKind {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct TypeKind;
|
enum TypeKind {
|
||||||
|
Function,
|
||||||
|
Constructor,
|
||||||
|
}
|
||||||
|
|
||||||
/// Keeps track of what names were used in a given namespace.
|
/// Keeps track of what names were used in a given namespace.
|
||||||
struct NameTable<K> {
|
struct NameTable<K> {
|
||||||
@ -114,7 +117,7 @@ impl SymbolTable {
|
|||||||
) -> Result<(), Vec<SymbolError>> {
|
) -> Result<(), Vec<SymbolError>> {
|
||||||
let mut populator = SymbolTablePopulator { type_context, table: self };
|
let mut populator = SymbolTablePopulator { type_context, table: self };
|
||||||
|
|
||||||
let errs = populator.populate_name_tables(ast);
|
let errs = populator.populate_definition_tables(ast);
|
||||||
if !errs.is_empty() {
|
if !errs.is_empty() {
|
||||||
return Err(errs);
|
return Err(errs);
|
||||||
}
|
}
|
||||||
@ -153,7 +156,8 @@ impl SymbolTable {
|
|||||||
/// to a Symbol, a descriptor of what that name refers to.
|
/// to a Symbol, a descriptor of what that name refers to.
|
||||||
fn add_symbol(&mut self, id: &ItemId, fqsn: Fqsn, spec: SymbolSpec) {
|
fn add_symbol(&mut self, id: &ItemId, fqsn: Fqsn, spec: SymbolSpec) {
|
||||||
let def_id = self.def_id_store.fresh();
|
let def_id = self.def_id_store.fresh();
|
||||||
let symbol = Rc::new(Symbol { fully_qualified_name: fqsn.clone(), spec, def_id });
|
let local_name = fqsn.last_elem();
|
||||||
|
let symbol = Rc::new(Symbol { fully_qualified_name: fqsn.clone(), local_name, spec, def_id });
|
||||||
self.symbol_trie.insert(&fqsn, def_id);
|
self.symbol_trie.insert(&fqsn, def_id);
|
||||||
self.id_to_def.insert(*id, def_id);
|
self.id_to_def.insert(*id, def_id);
|
||||||
self.def_to_symbol.insert(def_id, symbol);
|
self.def_to_symbol.insert(def_id, symbol);
|
||||||
@ -162,7 +166,8 @@ impl SymbolTable {
|
|||||||
fn populate_single_builtin(&mut self, fqsn: Fqsn, builtin: Builtin) {
|
fn populate_single_builtin(&mut self, fqsn: Fqsn, builtin: Builtin) {
|
||||||
let def_id = self.def_id_store.fresh();
|
let def_id = self.def_id_store.fresh();
|
||||||
let spec = SymbolSpec::Builtin(builtin);
|
let spec = SymbolSpec::Builtin(builtin);
|
||||||
let symbol = Rc::new(Symbol { fully_qualified_name: fqsn.clone(), spec, def_id });
|
let local_name = fqsn.last_elem();
|
||||||
|
let symbol = Rc::new(Symbol { fully_qualified_name: fqsn.clone(), local_name, spec, def_id });
|
||||||
|
|
||||||
self.symbol_trie.insert(&fqsn, def_id);
|
self.symbol_trie.insert(&fqsn, def_id);
|
||||||
self.def_to_symbol.insert(def_id, symbol);
|
self.def_to_symbol.insert(def_id, symbol);
|
||||||
@ -173,13 +178,14 @@ impl SymbolTable {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub struct Symbol {
|
pub struct Symbol {
|
||||||
fully_qualified_name: Fqsn,
|
fully_qualified_name: Fqsn,
|
||||||
|
local_name: Rc<String>,
|
||||||
spec: SymbolSpec,
|
spec: SymbolSpec,
|
||||||
def_id: DefId,
|
def_id: DefId,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Symbol {
|
impl Symbol {
|
||||||
pub fn local_name(&self) -> Rc<String> {
|
pub fn local_name(&self) -> &str {
|
||||||
self.fully_qualified_name.last_elem()
|
self.local_name.as_ref()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn def_id(&self) -> Option<DefId> {
|
pub fn def_id(&self) -> Option<DefId> {
|
||||||
@ -212,7 +218,7 @@ impl fmt::Display for Symbol {
|
|||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
pub enum SymbolSpec {
|
pub enum SymbolSpec {
|
||||||
Builtin(Builtin),
|
Builtin(Builtin),
|
||||||
Func,
|
Func { method: Option<crate::ast::TypeSingletonName> },
|
||||||
DataConstructor { tag: u32, type_id: TypeId },
|
DataConstructor { tag: u32, type_id: TypeId },
|
||||||
RecordConstructor { tag: u32, type_id: TypeId },
|
RecordConstructor { tag: u32, type_id: TypeId },
|
||||||
GlobalBinding, //Only for global variables, not for function-local ones or ones within a `let` scope context
|
GlobalBinding, //Only for global variables, not for function-local ones or ones within a `let` scope context
|
||||||
@ -225,7 +231,7 @@ impl fmt::Display for SymbolSpec {
|
|||||||
use self::SymbolSpec::*;
|
use self::SymbolSpec::*;
|
||||||
match self {
|
match self {
|
||||||
Builtin(b) => write!(f, "Builtin: {:?}", b),
|
Builtin(b) => write!(f, "Builtin: {:?}", b),
|
||||||
Func => write!(f, "Func"),
|
Func { .. } => write!(f, "Func"),
|
||||||
DataConstructor { tag, type_id } => write!(f, "DataConstructor(tag: {}, type: {})", tag, type_id),
|
DataConstructor { tag, type_id } => write!(f, "DataConstructor(tag: {}, type: {})", tag, type_id),
|
||||||
RecordConstructor { type_id, tag, .. } =>
|
RecordConstructor { type_id, tag, .. } =>
|
||||||
write!(f, "RecordConstructor(tag: {})(<members> -> {})", tag, type_id),
|
write!(f, "RecordConstructor(tag: {})(<members> -> {})", tag, type_id),
|
||||||
|
@ -1,6 +1,5 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::{hash_map::Entry, HashMap, HashSet},
|
collections::{hash_map::Entry, HashMap, HashSet},
|
||||||
rc::Rc,
|
|
||||||
str::FromStr,
|
str::FromStr,
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -32,7 +31,7 @@ impl<'a> SymbolTablePopulator<'a> {
|
|||||||
/// constants, functions, types, and modules defined within. This simultaneously
|
/// constants, functions, types, and modules defined within. This simultaneously
|
||||||
/// checks for dupicate definitions (and returns errors if discovered), and sets
|
/// checks for dupicate definitions (and returns errors if discovered), and sets
|
||||||
/// up name tables that will be used by further parts of the compiler
|
/// up name tables that will be used by further parts of the compiler
|
||||||
pub fn populate_name_tables(&mut self, ast: &AST) -> Vec<SymbolError> {
|
pub fn populate_definition_tables(&mut self, ast: &AST) -> Vec<SymbolError> {
|
||||||
let mut scope_stack = vec![];
|
let mut scope_stack = vec![];
|
||||||
self.add_from_scope(ast.statements.as_ref(), &mut scope_stack, false)
|
self.add_from_scope(ast.statements.as_ref(), &mut scope_stack, false)
|
||||||
}
|
}
|
||||||
@ -51,24 +50,36 @@ impl<'a> SymbolTablePopulator<'a> {
|
|||||||
if let Err(err) = self.add_single_statement(id, kind, location, scope_stack, function_scope) {
|
if let Err(err) = self.add_single_statement(id, kind, location, scope_stack, function_scope) {
|
||||||
errors.push(err);
|
errors.push(err);
|
||||||
} else {
|
} else {
|
||||||
|
let decl = match kind {
|
||||||
|
StatementKind::Declaration(decl) => decl,
|
||||||
|
_ => continue,
|
||||||
|
};
|
||||||
// If there's an error with a name, don't recurse into subscopes of that name
|
// If there's an error with a name, don't recurse into subscopes of that name
|
||||||
let recursive_errs = match kind {
|
let recursive_errs = match decl {
|
||||||
StatementKind::Declaration(Declaration::FuncDecl(signature, body)) => {
|
Declaration::FuncDecl(signature, body) => {
|
||||||
let new_scope = ScopeSegment::Name(signature.name.clone());
|
let new_scope = ScopeSegment::Name(signature.name.clone());
|
||||||
scope_stack.push(new_scope);
|
scope_stack.push(new_scope);
|
||||||
let output = self.add_from_scope(body.as_ref(), scope_stack, true);
|
let output = self.add_from_scope(body.as_ref(), scope_stack, true);
|
||||||
scope_stack.pop();
|
scope_stack.pop();
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
StatementKind::Declaration(Declaration::Module { name, items }) => {
|
Declaration::Module { name, items } => {
|
||||||
let new_scope = ScopeSegment::Name(name.clone());
|
let new_scope = ScopeSegment::Name(name.clone());
|
||||||
scope_stack.push(new_scope);
|
scope_stack.push(new_scope);
|
||||||
let output = self.add_from_scope(items.as_ref(), scope_stack, false);
|
let output = self.add_from_scope(items.as_ref(), scope_stack, false);
|
||||||
scope_stack.pop();
|
scope_stack.pop();
|
||||||
output
|
output
|
||||||
}
|
}
|
||||||
StatementKind::Declaration(Declaration::TypeDecl { name, body, mutable }) =>
|
Declaration::TypeDecl { name, body, mutable } => {
|
||||||
self.add_type_members(name, body, mutable, location, scope_stack),
|
let type_fqsn = Fqsn::from_scope_stack(scope_stack, name.name.clone());
|
||||||
|
self.add_type_members(name, body, mutable, location, type_fqsn)
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Declaration::Impl { type_name, body, .. } => {
|
||||||
|
|
||||||
|
},
|
||||||
|
*/
|
||||||
_ => vec![],
|
_ => vec![],
|
||||||
};
|
};
|
||||||
errors.extend(recursive_errs.into_iter());
|
errors.extend(recursive_errs.into_iter());
|
||||||
@ -92,9 +103,11 @@ impl<'a> SymbolTablePopulator<'a> {
|
|||||||
self.table
|
self.table
|
||||||
.fq_names
|
.fq_names
|
||||||
.register(fq_function.clone(), NameSpec { location, kind: NameKind::Function })?;
|
.register(fq_function.clone(), NameSpec { location, kind: NameKind::Function })?;
|
||||||
self.table.types.register(fq_function.clone(), NameSpec { location, kind: TypeKind })?;
|
self.table
|
||||||
|
.types
|
||||||
|
.register(fq_function.clone(), NameSpec { location, kind: TypeKind::Function })?;
|
||||||
|
|
||||||
self.add_symbol(id, fq_function, SymbolSpec::Func);
|
self.add_symbol(id, fq_function, SymbolSpec::Func { method: None });
|
||||||
}
|
}
|
||||||
StatementKind::Declaration(Declaration::FuncDecl(signature, ..)) => {
|
StatementKind::Declaration(Declaration::FuncDecl(signature, ..)) => {
|
||||||
let fn_name = &signature.name;
|
let fn_name = &signature.name;
|
||||||
@ -102,13 +115,15 @@ impl<'a> SymbolTablePopulator<'a> {
|
|||||||
self.table
|
self.table
|
||||||
.fq_names
|
.fq_names
|
||||||
.register(fq_function.clone(), NameSpec { location, kind: NameKind::Function })?;
|
.register(fq_function.clone(), NameSpec { location, kind: NameKind::Function })?;
|
||||||
self.table.types.register(fq_function.clone(), NameSpec { location, kind: TypeKind })?;
|
self.table
|
||||||
|
.types
|
||||||
|
.register(fq_function.clone(), NameSpec { location, kind: TypeKind::Function })?;
|
||||||
|
|
||||||
self.add_symbol(id, fq_function, SymbolSpec::Func);
|
self.add_symbol(id, fq_function, SymbolSpec::Func { method: None });
|
||||||
}
|
}
|
||||||
StatementKind::Declaration(Declaration::TypeDecl { name, .. }) => {
|
StatementKind::Declaration(Declaration::TypeDecl { name, .. }) => {
|
||||||
let fq_type = Fqsn::from_scope_stack(scope_stack, name.name.clone());
|
let fq_type = Fqsn::from_scope_stack(scope_stack, name.name.clone());
|
||||||
self.table.types.register(fq_type, NameSpec { location, kind: TypeKind })?;
|
self.table.types.register(fq_type, NameSpec { location, kind: TypeKind::Constructor })?;
|
||||||
}
|
}
|
||||||
StatementKind::Declaration(Declaration::Binding { name, .. }) => {
|
StatementKind::Declaration(Declaration::Binding { name, .. }) => {
|
||||||
let fq_binding = Fqsn::from_scope_stack(scope_stack, name.clone());
|
let fq_binding = Fqsn::from_scope_stack(scope_stack, name.clone());
|
||||||
@ -190,7 +205,7 @@ impl<'a> SymbolTablePopulator<'a> {
|
|||||||
type_body: &TypeBody,
|
type_body: &TypeBody,
|
||||||
_mutable: &bool,
|
_mutable: &bool,
|
||||||
location: Location,
|
location: Location,
|
||||||
scope_stack: &mut Vec<ScopeSegment>,
|
type_fqsn: Fqsn,
|
||||||
) -> Vec<SymbolError> {
|
) -> Vec<SymbolError> {
|
||||||
let (variants, immediate_variant) = match type_body {
|
let (variants, immediate_variant) = match type_body {
|
||||||
TypeBody::Variants(variants) => (variants.clone(), false),
|
TypeBody::Variants(variants) => (variants.clone(), false),
|
||||||
@ -203,10 +218,6 @@ impl<'a> SymbolTablePopulator<'a> {
|
|||||||
true,
|
true,
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
let type_fqsn = Fqsn::from_scope_stack(scope_stack, type_name.name.clone());
|
|
||||||
|
|
||||||
let new_scope = ScopeSegment::Name(type_name.name.clone());
|
|
||||||
scope_stack.push(new_scope);
|
|
||||||
|
|
||||||
// Check for duplicates before registering any types with the TypeContext
|
// Check for duplicates before registering any types with the TypeContext
|
||||||
let mut seen_variants = HashSet::new();
|
let mut seen_variants = HashSet::new();
|
||||||
@ -222,15 +233,15 @@ impl<'a> SymbolTablePopulator<'a> {
|
|||||||
seen_variants.insert(variant.name.clone());
|
seen_variants.insert(variant.name.clone());
|
||||||
|
|
||||||
if let VariantKind::Record(ref members) = variant.kind {
|
if let VariantKind::Record(ref members) = variant.kind {
|
||||||
let variant_name = Fqsn::from_scope_stack(scope_stack.as_ref(), variant.name.clone());
|
|
||||||
let mut seen_members = HashMap::new();
|
let mut seen_members = HashMap::new();
|
||||||
for (member_name, _) in members.iter() {
|
for (member_name, _) in members.iter() {
|
||||||
match seen_members.entry(member_name.as_ref()) {
|
match seen_members.entry(member_name.as_ref()) {
|
||||||
Entry::Occupied(o) => {
|
Entry::Occupied(o) => {
|
||||||
let location = *o.get();
|
let location = *o.get();
|
||||||
errors.push(SymbolError::DuplicateRecord {
|
errors.push(SymbolError::DuplicateRecord {
|
||||||
type_name: variant_name.clone(),
|
type_fqsn: type_fqsn.clone(),
|
||||||
location,
|
location,
|
||||||
|
record: variant.name.as_ref().to_string(),
|
||||||
member: member_name.as_ref().to_string(),
|
member: member_name.as_ref().to_string(),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -249,11 +260,11 @@ impl<'a> SymbolTablePopulator<'a> {
|
|||||||
|
|
||||||
let mut type_builder = TypeBuilder::new(type_name.name.as_ref());
|
let mut type_builder = TypeBuilder::new(type_name.name.as_ref());
|
||||||
|
|
||||||
let mut fqsn_id_map = HashMap::new();
|
let mut variant_name_map = HashMap::new();
|
||||||
for variant in variants.iter() {
|
for variant in variants.iter() {
|
||||||
let Variant { name, kind, id } = variant;
|
let Variant { name, kind, id } = variant;
|
||||||
|
|
||||||
fqsn_id_map.insert(Fqsn::from_scope_stack(scope_stack.as_ref(), name.clone()), id);
|
variant_name_map.insert(name.clone(), id);
|
||||||
|
|
||||||
let mut variant_builder = VariantBuilder::new(name.as_ref());
|
let mut variant_builder = VariantBuilder::new(name.as_ref());
|
||||||
match kind {
|
match kind {
|
||||||
@ -277,30 +288,23 @@ impl<'a> SymbolTablePopulator<'a> {
|
|||||||
|
|
||||||
// This index is guaranteed to be the correct tag
|
// This index is guaranteed to be the correct tag
|
||||||
for (index, variant) in type_definition.variants.iter().enumerate() {
|
for (index, variant) in type_definition.variants.iter().enumerate() {
|
||||||
let fqsn = Fqsn::from_scope_stack(scope_stack.as_ref(), Rc::new(variant.name.to_string()));
|
let id = variant_name_map.get(&variant.name).unwrap();
|
||||||
let id = fqsn_id_map.get(&fqsn).unwrap();
|
|
||||||
let tag = index as u32;
|
let tag = index as u32;
|
||||||
let spec = match &variant.members {
|
let spec = match &variant.members {
|
||||||
type_inference::VariantMembers::Unit => SymbolSpec::DataConstructor { tag, type_id },
|
type_inference::VariantMembers::Unit => SymbolSpec::DataConstructor { tag, type_id },
|
||||||
type_inference::VariantMembers::Tuple(..) => SymbolSpec::DataConstructor { tag, type_id },
|
type_inference::VariantMembers::Tuple(..) => SymbolSpec::DataConstructor { tag, type_id },
|
||||||
type_inference::VariantMembers::Record(..) => SymbolSpec::RecordConstructor { tag, type_id },
|
type_inference::VariantMembers::Record(..) => SymbolSpec::RecordConstructor { tag, type_id },
|
||||||
};
|
};
|
||||||
self.table.add_symbol(id, fqsn, spec);
|
self.table.add_symbol(id, type_fqsn.extend(&variant.name), spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
if immediate_variant {
|
if immediate_variant {
|
||||||
let variant = &type_definition.variants[0];
|
let variant = &type_definition.variants[0];
|
||||||
let fqsn = Fqsn::from_scope_stack(scope_stack.as_ref(), Rc::new(variant.name.to_string()));
|
let id = variant_name_map.get(&variant.name).unwrap();
|
||||||
let id = fqsn_id_map.get(&fqsn).unwrap();
|
|
||||||
let abbrev_fqsn = Fqsn::from_scope_stack(
|
|
||||||
scope_stack[0..scope_stack.len() - 1].as_ref(),
|
|
||||||
Rc::new(variant.name.to_string()),
|
|
||||||
);
|
|
||||||
let spec = SymbolSpec::RecordConstructor { tag: 0, type_id };
|
let spec = SymbolSpec::RecordConstructor { tag: 0, type_id };
|
||||||
self.table.add_symbol(id, abbrev_fqsn, spec);
|
self.table.add_symbol(id, type_fqsn, spec);
|
||||||
}
|
}
|
||||||
|
|
||||||
scope_stack.pop();
|
|
||||||
vec![]
|
vec![]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -263,10 +263,29 @@ fn duplicate_struct_members() {
|
|||||||
"#;
|
"#;
|
||||||
|
|
||||||
let (_, output) = add_symbols(source);
|
let (_, output) = add_symbols(source);
|
||||||
let errs = output.unwrap_err();
|
let errs = dbg!(output.unwrap_err());
|
||||||
assert_matches!(&errs[..], [
|
assert_matches!(&errs[..], [
|
||||||
SymbolError::DuplicateRecord {
|
SymbolError::DuplicateRecord {
|
||||||
type_name, member, ..},
|
type_fqsn, member, record, ..},
|
||||||
] if type_name == &Fqsn::from_strs(&["Tarak", "Tarak"]) && member == "mets"
|
] if type_fqsn == &Fqsn::from_strs(&["Tarak"]) && member == "mets" && record == "Tarak"
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[test]
|
||||||
|
fn methods() {
|
||||||
|
let source = r#"
|
||||||
|
|
||||||
|
type Foo = { x: Int, y: Int }
|
||||||
|
|
||||||
|
impl Foo {
|
||||||
|
fn hella() {
|
||||||
|
self.x + 50
|
||||||
|
}
|
||||||
|
}
|
||||||
|
"#;
|
||||||
|
let (symbols, _) = add_symbols(source);
|
||||||
|
symbols.debug();
|
||||||
|
assert!(symbols.fq_names.table.get(&make_fqsn(&["hella"])).is_some());
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
Loading…
Reference in New Issue
Block a user