Make StringIdx Copy.

This commit is contained in:
James Harton 2019-04-04 08:23:31 +13:00
parent 87f4b970f6
commit 1d3815e281
7 changed files with 80 additions and 82 deletions

View file

@ -51,7 +51,7 @@ fn fmt_errors(buffer: &mut String, context: &Context) {
fn fmt_ty_name(idx: &TyIdx, context: &Context) -> String { fn fmt_ty_name(idx: &TyIdx, context: &Context) -> String {
if let Some(ty) = context.get_type(idx) { if let Some(ty) = context.get_type(idx) {
if let Some(name) = ty.name() { if let Some(name) = ty.name() {
return context.get_string(&name).unwrap().to_string(); return context.get_string(name).unwrap().to_string();
} }
if ty.is_impl() { if ty.is_impl() {
let tr = fmt_ty_name(ty.impl_of().unwrap(), &context); let tr = fmt_ty_name(ty.impl_of().unwrap(), &context);
@ -74,7 +74,7 @@ fn fmt_types(buffer: &mut String, context: &Context) {
for (i, ty) in context.types.iter().enumerate() { for (i, ty) in context.types.iter().enumerate() {
if let Some(name) = ty.name() { if let Some(name) = ty.name() {
let name = context.get_string(&name).unwrap(); let name = context.get_string(name).unwrap();
buffer.push_str(&format!("{} = ", name)); buffer.push_str(&format!("{} = ", name));
} else if ty.is_impl() { } else if ty.is_impl() {
let tr = fmt_ty_name(ty.impl_of().unwrap(), &context); let tr = fmt_ty_name(ty.impl_of().unwrap(), &context);
@ -113,7 +113,7 @@ fn fmt_types(buffer: &mut String, context: &Context) {
buffer.push_str("<"); buffer.push_str("<");
} }
let name = context.get_string(name).unwrap(); let name = context.get_string(**name).unwrap();
let ty = fmt_ty_name(ty, &context); let ty = fmt_ty_name(ty, &context);
buffer.push_str(&format!("{}: {}", name, ty)); buffer.push_str(&format!("{}: {}", name, ty));
@ -185,7 +185,7 @@ fn fmt_functions(mut buffer: &mut String, context: &Context) {
buffer.push_str("("); buffer.push_str("(");
} }
let name = context.get_string(name).unwrap(); let name = context.get_string(**name).unwrap();
let ty = fmt_ty_name(ty, &context); let ty = fmt_ty_name(ty, &context);
buffer.push_str(&format!("{}: {}", name, ty)); buffer.push_str(&format!("{}: {}", name, ty));
@ -299,7 +299,7 @@ fn fmt_ir(
} }
} else if value.is_atom() { } else if value.is_atom() {
let atom = value.atom().unwrap(); let atom = value.atom().unwrap();
let atom = context.get_string(atom).unwrap(); let atom = context.get_string(*atom).unwrap();
*i += 1; *i += 1;
buffer.push_str(&format!(" v{:0>2}: {}", i, atom)); buffer.push_str(&format!(" v{:0>2}: {}", i, atom));
} else if value.is_boolean() { } else if value.is_boolean() {
@ -342,7 +342,7 @@ fn fmt_ir(
} }
} else if value.is_string() { } else if value.is_string() {
let string = value.string().unwrap(); let string = value.string().unwrap();
let string = context.get_string(string).unwrap(); let string = context.get_string(*string).unwrap();
*i += 1; *i += 1;
buffer.push_str(&format!(" v{:0>2}: {:?}", *i, string)); buffer.push_str(&format!(" v{:0>2}: {:?}", *i, string));
} }
@ -361,7 +361,7 @@ fn fmt_ir(
buffer.push_str("{"); buffer.push_str("{");
} }
let key = context.get_string(key).unwrap(); let key = context.get_string(*key).unwrap();
buffer.push_str(&format!("{}: v{:0>2}", key, ivs[j])); buffer.push_str(&format!("{}: v{:0>2}", key, ivs[j]));
if j == ivs.len() - 1 { if j == ivs.len() - 1 {
@ -375,11 +375,11 @@ fn fmt_ir(
*i += 1; *i += 1;
buffer.push_str(&format!(" v{:0>2}: ref f{}", *i, usize::from(idx))); buffer.push_str(&format!(" v{:0>2}: ref f{}", *i, usize::from(idx)));
} else if ir.is_get_local() { } else if ir.is_get_local() {
let name = context.get_string(ir.get_local().unwrap()).unwrap(); let name = context.get_string(*ir.get_local().unwrap()).unwrap();
*i += 1; *i += 1;
buffer.push_str(&format!(" v{:0>2}: get {}", *i, name)); buffer.push_str(&format!(" v{:0>2}: get {}", *i, name));
} else if ir.is_get_property() { } else if ir.is_get_property() {
let name = context.get_string(ir.get_property().unwrap()).unwrap(); let name = context.get_string(*ir.get_property().unwrap()).unwrap();
*i += 1; *i += 1;
buffer.push_str(&format!(" v{:0>2}: get @{}", *i, name)); buffer.push_str(&format!(" v{:0>2}: get @{}", *i, name));
} else if ir.is_infix() { } else if ir.is_infix() {
@ -419,7 +419,7 @@ fn fmt_ir(
let (rx, name, args) = ir.get_method_call().unwrap(); let (rx, name, args) = ir.get_method_call().unwrap();
fmt_ir(&mut buffer, &context, rx, &mut i, &mut jumps); fmt_ir(&mut buffer, &context, rx, &mut i, &mut jumps);
let rx = *i; let rx = *i;
let name = context.get_string(name).unwrap(); let name = context.get_string(*name).unwrap();
let mut ivs = Vec::new(); let mut ivs = Vec::new();
for arg in args { for arg in args {
fmt_ir(&mut buffer, &context, arg, &mut i, &mut jumps); fmt_ir(&mut buffer, &context, arg, &mut i, &mut jumps);
@ -453,7 +453,7 @@ fn fmt_ir(
let (name, value) = ir.get_set_local().unwrap(); let (name, value) = ir.get_set_local().unwrap();
fmt_ir(&mut buffer, &context, value, &mut i, &mut jumps); fmt_ir(&mut buffer, &context, value, &mut i, &mut jumps);
let value = *i; let value = *i;
let name = context.get_string(name).unwrap(); let name = context.get_string(*name).unwrap();
*i += 1; *i += 1;
buffer.push_str(&format!(" v{:0>2}: set {} v{:0>2}", *i, name, value)); buffer.push_str(&format!(" v{:0>2}: set {} v{:0>2}", *i, name, value));
} else if ir.is_set_properties() { } else if ir.is_set_properties() {
@ -470,7 +470,7 @@ fn fmt_ir(
buffer.push_str("@{"); buffer.push_str("@{");
} }
let key = context.get_string(key).unwrap(); let key = context.get_string(*key).unwrap();
buffer.push_str(&format!("{}: v{:0>2}", key, ivs[j])); buffer.push_str(&format!("{}: v{:0>2}", key, ivs[j]));
if j == ivs.len() - 1 { if j == ivs.len() - 1 {
@ -505,7 +505,7 @@ fn fmt_methods(mut buffer: &mut String, context: &Context) {
for method in &context.methods { for method in &context.methods {
let parent_type = fmt_ty_name(method.parent_type(), &context); let parent_type = fmt_ty_name(method.parent_type(), &context);
let name = context.get_string(method.name()).unwrap(); let name = context.get_string(*method.name()).unwrap();
let sigil = if method.is_static() { "." } else { "#" }; let sigil = if method.is_static() { "." } else { "#" };
for clause in method.clauses() { for clause in method.clauses() {
@ -520,7 +520,7 @@ fn fmt_methods(mut buffer: &mut String, context: &Context) {
buffer.push_str("("); buffer.push_str("(");
} }
let name = context.get_string(name).unwrap(); let name = context.get_string(**name).unwrap();
let ty = fmt_ty_name(ty, &context); let ty = fmt_ty_name(ty, &context);
buffer.push_str(&format!("{}: {}", name, ty)); buffer.push_str(&format!("{}: {}", name, ty));

View file

@ -58,7 +58,7 @@ impl Context {
} }
pub fn current_file(&self) -> &str { pub fn current_file(&self) -> &str {
self.strings.get(&self.current_file).unwrap() self.strings.get(self.current_file).unwrap()
} }
/// Define a function in the context and return a reference to it. /// Define a function in the context and return a reference to it.
@ -86,21 +86,21 @@ impl Context {
/// Declare a trait type. /// Declare a trait type.
pub fn declare_trait( pub fn declare_trait(
&mut self, &mut self,
name: &StringIdx, name: StringIdx,
requirements: Vec<TyIdx>, requirements: Vec<TyIdx>,
location: Location, location: Location,
) -> TyIdx { ) -> TyIdx {
if self if self
.types .types
.iter() .iter()
.any(|t| t.name() == Some(name.clone()) && !t.is_unresolved()) .any(|t| t.name() == Some(name) && !t.is_unresolved())
{ {
let message = format!("Type {} redefined", self.get_string(name).unwrap()); let message = format!("Type {} redefined", self.get_string(name).unwrap());
self.compile_error(&message, location.clone(), ErrorKind::TypeRedefined); self.compile_error(&message, location.clone(), ErrorKind::TypeRedefined);
} }
let idx = self.types.len(); let idx = self.types.len();
let ty = Ty::new_trait(Some(name.clone()), location, requirements); let ty = Ty::new_trait(Some(name), location, requirements);
self.types.push(ty); self.types.push(ty);
idx.into() idx.into()
} }
@ -108,21 +108,21 @@ impl Context {
/// Declare a user type. /// Declare a user type.
pub fn declare_type( pub fn declare_type(
&mut self, &mut self,
name: &StringIdx, name: StringIdx,
properties: Vec<(StringIdx, TyIdx)>, properties: Vec<(StringIdx, TyIdx)>,
location: Location, location: Location,
) -> TyIdx { ) -> TyIdx {
if self if self
.types .types
.iter() .iter()
.any(|t| t.name() == Some(name.clone()) && !t.is_unresolved()) .any(|t| t.name() == Some(name) && !t.is_unresolved())
{ {
let message = format!("Type {} redefined", self.get_string(name).unwrap()); let message = format!("Type {} redefined", self.get_string(name).unwrap());
self.compile_error(&message, location.clone(), ErrorKind::TypeRedefined) self.compile_error(&message, location.clone(), ErrorKind::TypeRedefined)
} }
let idx = self.types.len(); let idx = self.types.len();
let ty = Ty::new_type(name.clone(), location, properties); let ty = Ty::new_type(name, location, properties);
self.types.push(ty); self.types.push(ty);
idx.into() idx.into()
} }
@ -131,11 +131,11 @@ impl Context {
pub fn find_method( pub fn find_method(
&self, &self,
parent_type: &TyIdx, parent_type: &TyIdx,
name: &StringIdx, name: StringIdx,
modifier: Modifier, modifier: Modifier,
) -> Option<MethodIdx> { ) -> Option<MethodIdx> {
for (idx, method) in self.methods.iter().enumerate() { for (idx, method) in self.methods.iter().enumerate() {
if method.name() == name if method.name() == &name
&& method.parent_type() == parent_type && method.parent_type() == parent_type
&& method.modifier() == modifier && method.modifier() == modifier
{ {
@ -148,7 +148,7 @@ impl Context {
#[cfg(test)] #[cfg(test)]
pub fn find_type(&mut self, name: &str) -> Option<&Ty> { pub fn find_type(&mut self, name: &str) -> Option<&Ty> {
let name = self.constant_string(name); let name = self.constant_string(name);
self.types.iter().find(|ty| ty.name() == Some(name.clone())) self.types.iter().find(|ty| ty.name() == Some(name))
} }
/// Retrieve a specific block by it's index. /// Retrieve a specific block by it's index.
@ -173,7 +173,7 @@ impl Context {
self.methods.get_mut(usize::from(idx)) self.methods.get_mut(usize::from(idx))
} }
pub fn get_string(&self, idx: &StringIdx) -> Option<&str> { pub fn get_string(&self, idx: StringIdx) -> Option<&str> {
self.strings.get(idx) self.strings.get(idx)
} }
@ -245,7 +245,7 @@ impl Context {
/// Convert an AST `InputLocation` into a compiler `Location`. /// Convert an AST `InputLocation` into a compiler `Location`.
pub fn location(&self, location: &InputLocation) -> Location { pub fn location(&self, location: &InputLocation) -> Location {
let path = self.strings.get(&self.current_file).unwrap(); let path = self.strings.get(self.current_file).unwrap();
Location::new(location.clone(), path) Location::new(location.clone(), path)
} }
@ -292,19 +292,19 @@ impl Context {
/// Create a (potentially unresolved) type reference based on the name of /// Create a (potentially unresolved) type reference based on the name of
/// the specified type. /// the specified type.
pub fn reference_type(&mut self, name: &StringIdx, location: Location) -> TyIdx { pub fn reference_type(&mut self, name: StringIdx, location: Location) -> TyIdx {
// Try and eagerly dereference types if we can. // Try and eagerly dereference types if we can.
// This can theoretically return another type reference, so we still // This can theoretically return another type reference, so we still
// have to do a full type-check. // have to do a full type-check.
for (i, ty) in self.types.iter().enumerate() { for (i, ty) in self.types.iter().enumerate() {
if ty.name() == Some(name.clone()) { if ty.name() == Some(name) {
return i.into(); return i.into();
} }
} }
// Otherwise create a new type reference. // Otherwise create a new type reference.
let idx = self.types.len(); let idx = self.types.len();
let ty = Ty::new_reference(name.clone(), location); let ty = Ty::new_reference(name, location);
self.types.push(ty); self.types.push(ty);
idx.into() idx.into()
} }
@ -336,9 +336,9 @@ mod test {
let s0 = context.constant_string("Marty McFly"); let s0 = context.constant_string("Marty McFly");
let s1 = context.constant_string("Doc Brown"); let s1 = context.constant_string("Doc Brown");
let t0 = context.declare_type(&s0, Vec::new(), Location::test()); let t0 = context.declare_type(s0, Vec::new(), Location::test());
let t1 = context.reference_type(&s0, Location::test()); let t1 = context.reference_type(s0, Location::test());
let t2 = context.reference_type(&s1, Location::test()); let t2 = context.reference_type(s1, Location::test());
assert_eq!(t0, t1); assert_eq!(t0, t1);
assert_ne!(t0, t2); assert_ne!(t0, t2);
@ -367,12 +367,12 @@ mod test {
let s = context.constant_string("Marty McFly"); let s = context.constant_string("Marty McFly");
context.declare_type(&s, Vec::default(), Location::test()); context.declare_type(s, Vec::default(), Location::test());
context.reference_type(&s, Location::test()); context.reference_type(s, Location::test());
assert!(context.errors.is_empty()); assert!(context.errors.is_empty());
context.declare_trait(&s, Vec::default(), Location::test()); context.declare_trait(s, Vec::default(), Location::test());
assert!(!context.errors.is_empty()); assert!(!context.errors.is_empty());
} }

View file

@ -24,7 +24,7 @@ pub fn pass(ir: &mut IR, context: &mut Context) {
if let Some(value) = value { if let Some(value) = value {
ir.set_kind(IRKind::Constant(Val::Integer(value))); ir.set_kind(IRKind::Constant(Val::Integer(value)));
let idx = context.constant_string("Huia.Native.Integer"); let idx = context.constant_string("Huia.Native.Integer");
ir.set_result_type(context.reference_type(&idx, ir.get_location().clone())); ir.set_result_type(context.reference_type(idx, ir.get_location().clone()));
} }
} else if lhs.is_float() && rhs.is_float() { } else if lhs.is_float() && rhs.is_float() {
let lhs = lhs.float().unwrap(); let lhs = lhs.float().unwrap();
@ -33,7 +33,7 @@ pub fn pass(ir: &mut IR, context: &mut Context) {
if let Some(value) = value { if let Some(value) = value {
ir.set_kind(IRKind::Constant(Val::Float(value))); ir.set_kind(IRKind::Constant(Val::Float(value)));
let idx = context.constant_string("Huia.Native.Float"); let idx = context.constant_string("Huia.Native.Float");
ir.set_result_type(context.reference_type(&idx, ir.get_location().clone())); ir.set_result_type(context.reference_type(idx, ir.get_location().clone()));
} }
} }
} }

View file

@ -25,7 +25,7 @@ pub fn pass(ir: &mut IR, context: &mut Context) {
ir.set_kind(IRKind::Constant(Val::Boolean(false))); ir.set_kind(IRKind::Constant(Val::Boolean(false)));
} }
let tyname = context.constant_string("Huia.Native.Boolean"); let tyname = context.constant_string("Huia.Native.Boolean");
let ty = context.reference_type(&tyname, ir.get_location().clone()); let ty = context.reference_type(tyname, ir.get_location().clone());
ir.set_result_type(ty) ir.set_result_type(ty)
} }
UnOp::Minus => { UnOp::Minus => {

View file

@ -29,7 +29,7 @@ impl Builder {
NodeType::Array => { NodeType::Array => {
let ty_idx = context.constant_string("Huia.Native.Array"); let ty_idx = context.constant_string("Huia.Native.Array");
let location = context.location(&node.location()); let location = context.location(&node.location());
let ty = context.reference_type(&ty_idx, location.clone()); let ty = context.reference_type(ty_idx, location.clone());
let elements = node let elements = node
.array() .array()
@ -45,14 +45,14 @@ impl Builder {
NodeType::Atom => { NodeType::Atom => {
let ty_idx = context.constant_string("Huia.Native.Atom"); let ty_idx = context.constant_string("Huia.Native.Atom");
let location = context.location(&node.location()); let location = context.location(&node.location());
let ty = context.reference_type(&ty_idx, location.clone()); let ty = context.reference_type(ty_idx, location.clone());
let idx = context.constant_string(node.atom().unwrap().value_ref().as_str()); let idx = context.constant_string(node.atom().unwrap().value_ref().as_str());
self.push_ir(IR::new_constant(ty, location, Val::Atom(idx))); self.push_ir(IR::new_constant(ty, location, Val::Atom(idx)));
} }
NodeType::Boolean => { NodeType::Boolean => {
let ty_idx = context.constant_string("Huia.Native.Boolean"); let ty_idx = context.constant_string("Huia.Native.Boolean");
let location = context.location(&node.location()); let location = context.location(&node.location());
let ty = context.reference_type(&ty_idx, location.clone()); let ty = context.reference_type(ty_idx, location.clone());
let value = *node.boolean().unwrap().value_ref(); let value = *node.boolean().unwrap().value_ref();
self.push_ir(IR::new_constant(ty, location, Val::Boolean(value))); self.push_ir(IR::new_constant(ty, location, Val::Boolean(value)));
} }
@ -66,7 +66,7 @@ impl Builder {
let result_type = if op.is_logical() { let result_type = if op.is_logical() {
let name = context.constant_string("Huia.Native.Boolean"); let name = context.constant_string("Huia.Native.Boolean");
context.reference_type(&name, location.clone()) context.reference_type(name, location.clone())
} }
else if op.is_arithmetic() { else if op.is_arithmetic() {
lhs.result_type().clone() lhs.result_type().clone()
@ -103,7 +103,7 @@ impl Builder {
let (ty, props) = node.constructor().unwrap(); let (ty, props) = node.constructor().unwrap();
let ty_idx = context.constant_string(ty.value_ref().as_str()); let ty_idx = context.constant_string(ty.value_ref().as_str());
let location = context.location(&node.location()); let location = context.location(&node.location());
let ty = context.reference_type(&ty_idx, location.clone()); let ty = context.reference_type(ty_idx, location.clone());
let properties = props let properties = props
.iter() .iter()
@ -122,13 +122,13 @@ impl Builder {
let name = context.constant_string(name.value_ref().as_str()); let name = context.constant_string(name.value_ref().as_str());
self.build(rhs.clone(), &mut context); self.build(rhs.clone(), &mut context);
let rhs = self.pop_ir().unwrap(); let rhs = self.pop_ir().unwrap();
self.env_set(&name, &rhs.result_type()); self.env_set(name, &rhs.result_type());
self.push_ir(IR::new_set_local(rhs.result_type().clone(), location, name, rhs)); self.push_ir(IR::new_set_local(rhs.result_type().clone(), location, name, rhs));
} }
NodeType::Float => { NodeType::Float => {
let ty_idx = context.constant_string("Huia.Native.Float"); let ty_idx = context.constant_string("Huia.Native.Float");
let location = context.location(&node.location()); let location = context.location(&node.location());
let ty = context.reference_type(&ty_idx, location.clone()); let ty = context.reference_type(ty_idx, location.clone());
let value = *node.float().unwrap().value_ref(); let value = *node.float().unwrap().value_ref();
self.push_ir(IR::new_constant(ty, location, Val::Float(value))); self.push_ir(IR::new_constant(ty, location, Val::Float(value)));
} }
@ -154,7 +154,7 @@ impl Builder {
let test = self.pop_ir().unwrap(); let test = self.pop_ir().unwrap();
let result_type = context.unknown_type(location.clone()); let result_type = context.unknown_type(location.clone());
let value_var_name = context.constant_string("$if_tmp"); let value_var_name = context.constant_string("$if_tmp");
self.env_set(&value_var_name, &result_type); self.env_set(value_var_name, &result_type);
let mut following_block_idx = usize::from(context.next_block_idx()); let mut following_block_idx = usize::from(context.next_block_idx());
@ -171,7 +171,7 @@ impl Builder {
if let Some(last_ir) = self.pop_ir() { if let Some(last_ir) = self.pop_ir() {
let rt = context.get_type_mut(&result_type).unwrap(); let rt = context.get_type_mut(&result_type).unwrap();
rt.resolve(&last_ir.result_type()); rt.resolve(&last_ir.result_type());
self.push_ir(IR::new_set_local(last_ir.result_type().clone(), location.clone(), value_var_name.clone(), last_ir.clone())); self.push_ir(IR::new_set_local(last_ir.result_type().clone(), location.clone(), value_var_name, last_ir.clone()));
self.push_ir(IR::new_jump(last_ir.result_type().clone(), location.clone(), following_block_idx.into())); self.push_ir(IR::new_jump(last_ir.result_type().clone(), location.clone(), following_block_idx.into()));
} else { } else {
self.push_ir(IR::new_jump(result_type.clone(), location.clone(), following_block_idx.into())); self.push_ir(IR::new_jump(result_type.clone(), location.clone(), following_block_idx.into()));
@ -202,7 +202,7 @@ impl Builder {
context.compile_error("Both branches of an if statement must result in the same type.", location.clone(), ErrorKind::InconsistentBranchTypes); context.compile_error("Both branches of an if statement must result in the same type.", location.clone(), ErrorKind::InconsistentBranchTypes);
} }
self.push_ir(IR::new_set_local(last_ir.result_type().clone(), location.clone(), value_var_name.clone(), last_ir.clone())); self.push_ir(IR::new_set_local(last_ir.result_type().clone(), location.clone(), value_var_name, last_ir.clone()));
self.push_ir(IR::new_jump(last_ir.result_type().clone(), location.clone(), following_block_idx.into())); self.push_ir(IR::new_jump(last_ir.result_type().clone(), location.clone(), following_block_idx.into()));
} else { } else {
self.push_ir(IR::new_jump(result_type.clone(), location.clone(), following_block_idx.into())); self.push_ir(IR::new_jump(result_type.clone(), location.clone(), following_block_idx.into()));
@ -221,7 +221,7 @@ impl Builder {
// Finally, push the following block onto the stack for the following instructions. // Finally, push the following block onto the stack for the following instructions.
self.push_block(context.unknown_type(location.clone())); self.push_block(context.unknown_type(location.clone()));
if let Some(result_type) = self.env_get(&value_var_name) { if let Some(result_type) = self.env_get(value_var_name) {
self.push_ir(IR::new_get_local(result_type.clone(), location, value_var_name)); self.push_ir(IR::new_get_local(result_type.clone(), location, value_var_name));
} }
} }
@ -229,7 +229,7 @@ impl Builder {
let (ty, body) = node.impldef().unwrap(); let (ty, body) = node.impldef().unwrap();
let ty_idx = context.constant_string(ty.value_ref().as_str()); let ty_idx = context.constant_string(ty.value_ref().as_str());
let location = context.location(&node.location()); let location = context.location(&node.location());
let tr = context.reference_type(&ty_idx, location.clone()); let tr = context.reference_type(ty_idx, location.clone());
// the parser state should stop us from being in an // the parser state should stop us from being in an
// implementation whilst not inside a type definition. // implementation whilst not inside a type definition.
@ -251,7 +251,7 @@ impl Builder {
NodeType::Integer => { NodeType::Integer => {
let ty_idx = context.constant_string("Huia.Native.Integer"); let ty_idx = context.constant_string("Huia.Native.Integer");
let location = context.location(&node.location()); let location = context.location(&node.location());
let ty = context.reference_type(&ty_idx, location.clone()); let ty = context.reference_type(ty_idx, location.clone());
let value = *node.integer().unwrap().value_ref(); let value = *node.integer().unwrap().value_ref();
self.push_ir(IR::new_constant(ty, location, Val::Integer(value))); self.push_ir(IR::new_constant(ty, location, Val::Integer(value)));
} }
@ -260,7 +260,7 @@ impl Builder {
let name = name.value_ref().as_str(); let name = name.value_ref().as_str();
let location = context.location(&node.location()); let location = context.location(&node.location());
let constant_name = context.constant_string(name); let constant_name = context.constant_string(name);
match self.env_get(&constant_name) { match self.env_get(constant_name) {
Some(result_type) => self.push_ir(IR::new_get_local(result_type.clone(), location, constant_name)), Some(result_type) => self.push_ir(IR::new_get_local(result_type.clone(), location, constant_name)),
None => { None => {
// Add a compiler error. // Add a compiler error.
@ -276,7 +276,7 @@ impl Builder {
NodeType::Map => { NodeType::Map => {
let ty_idx = context.constant_string("Huia.Native.Map"); let ty_idx = context.constant_string("Huia.Native.Map");
let location = context.location(&node.location()); let location = context.location(&node.location());
let ty = context.reference_type(&ty_idx, location.clone()); let ty = context.reference_type(ty_idx, location.clone());
let elements = node let elements = node
.map() .map()
@ -312,7 +312,7 @@ impl Builder {
let location = context.location(&node.location()); let location = context.location(&node.location());
let name = let name =
context.constant_string(node.property_get().unwrap().value_ref().as_str()); context.constant_string(node.property_get().unwrap().value_ref().as_str());
let result_type = self.prop_ty(&name, &context).unwrap(); let result_type = self.prop_ty(name, &context).unwrap();
self.push_ir(IR::new_get_property(result_type, location, name)); self.push_ir(IR::new_get_property(result_type, location, name));
} }
NodeType::PropertySet => { NodeType::PropertySet => {
@ -338,14 +338,14 @@ impl Builder {
let (ident, arguments, body) = node.private_method().unwrap(); let (ident, arguments, body) = node.private_method().unwrap();
let method_name = context.constant_string(ident.value_ref().as_str()); let method_name = context.constant_string(ident.value_ref().as_str());
let modifier = Modifier::Private; let modifier = Modifier::Private;
self.build_method(&mut context, &method_name, modifier, location, arguments, body); self.build_method(&mut context, method_name, modifier, location, arguments, body);
} }
NodeType::PublicMethod => { NodeType::PublicMethod => {
let location = context.location(&node.location()); let location = context.location(&node.location());
let (ident, arguments, body) = node.public_method().unwrap(); let (ident, arguments, body) = node.public_method().unwrap();
let method_name = context.constant_string(ident.value_ref().as_str()); let method_name = context.constant_string(ident.value_ref().as_str());
let modifier = Modifier::Public; let modifier = Modifier::Public;
self.build_method(&mut context, &method_name, modifier, location, arguments, body); self.build_method(&mut context, method_name, modifier, location, arguments, body);
} }
NodeType::PublicMethodSpec => { NodeType::PublicMethodSpec => {
let location = context.location(&node.location()); let location = context.location(&node.location());
@ -364,7 +364,7 @@ impl Builder {
let (ident, arguments, body) = node.static_method().unwrap(); let (ident, arguments, body) = node.static_method().unwrap();
let method_name = context.constant_string(ident.value_ref().as_str()); let method_name = context.constant_string(ident.value_ref().as_str());
let modifier = Modifier::Static; let modifier = Modifier::Static;
self.build_method(&mut context, &method_name, modifier, location, arguments, body); self.build_method(&mut context, method_name, modifier, location, arguments, body);
} }
NodeType::StaticMethodSpec => { NodeType::StaticMethodSpec => {
let location = context.location(&node.location()); let location = context.location(&node.location());
@ -381,7 +381,7 @@ impl Builder {
NodeType::String => { NodeType::String => {
let ty_idx = context.constant_string("Huia.Native.String"); let ty_idx = context.constant_string("Huia.Native.String");
let location = context.location(&node.location()); let location = context.location(&node.location());
let ty = context.reference_type(&ty_idx, location.clone()); let ty = context.reference_type(ty_idx, location.clone());
let idx = context.constant_string(node.string().unwrap().value_ref().as_str()); let idx = context.constant_string(node.string().unwrap().value_ref().as_str());
self.push_ir(IR::new_constant(ty, location, Val::String(idx))); self.push_ir(IR::new_constant(ty, location, Val::String(idx)));
} }
@ -398,14 +398,14 @@ impl Builder {
.map(|node| { .map(|node| {
let name = context.constant_string(node.value_ref().as_str()); let name = context.constant_string(node.value_ref().as_str());
let location = context.location(&node.location()); let location = context.location(&node.location());
context.reference_type(&name, location) context.reference_type(name, location)
}) })
.collect() .collect()
} else { } else {
Vec::new() Vec::new()
}; };
let ty = context.declare_trait(&ty_idx, types, location.clone()); let ty = context.declare_trait(ty_idx, types, location.clone());
self.push_ty(ty.clone()); self.push_ty(ty.clone());
self.push_block(context.unknown_type(location)); self.push_block(context.unknown_type(location));
@ -420,9 +420,9 @@ impl Builder {
NodeType::Ty => { NodeType::Ty => {
let location = context.location(&node.location()); let location = context.location(&node.location());
let result_type_idx = context.constant_string("Huia.Native.Type"); let result_type_idx = context.constant_string("Huia.Native.Type");
let result_type = context.reference_type(&result_type_idx, location.clone()); let result_type = context.reference_type(result_type_idx, location.clone());
let ty_idx = context.constant_string(node.ty().unwrap().value_ref().as_str()); let ty_idx = context.constant_string(node.ty().unwrap().value_ref().as_str());
let ty = context.reference_type(&ty_idx, location.clone()); let ty = context.reference_type(ty_idx, location.clone());
self.push_ir(IR::new_type_reference(result_type, location, ty)); self.push_ir(IR::new_type_reference(result_type, location, ty));
} }
NodeType::TypeDef => { NodeType::TypeDef => {
@ -439,7 +439,7 @@ impl Builder {
}) })
.collect(); .collect();
let ty = context.declare_type(&ty_idx, properties, location.clone()); let ty = context.declare_type(ty_idx, properties, location.clone());
self.push_ty(ty.clone()); self.push_ty(ty.clone());
self.push_block(context.unknown_type(location)); self.push_block(context.unknown_type(location));
for node in body { for node in body {
@ -475,7 +475,7 @@ impl Builder {
.map(|node| { .map(|node| {
let name = context.constant_string(node.value_ref().as_str()); let name = context.constant_string(node.value_ref().as_str());
let location = context.location(&node.location()); let location = context.location(&node.location());
context.reference_type(&name, location) context.reference_type(name, location)
}) })
.collect(); .collect();
context.anonymous_trait(types, location) context.anonymous_trait(types, location)
@ -508,7 +508,7 @@ impl Builder {
let current_block_len = self.blocks.len(); let current_block_len = self.blocks.len();
for (name, ty) in &arguments { for (name, ty) in &arguments {
self.env_set(name, ty); self.env_set(*name, ty);
} }
for node in body { for node in body {
@ -558,7 +558,7 @@ impl Builder {
fn build_method( fn build_method(
&mut self, &mut self,
mut context: &mut Context, mut context: &mut Context,
method_name: &StringIdx, method_name: StringIdx,
modifier: Modifier, modifier: Modifier,
location: Loc, location: Loc,
arguments: &[(Identifier, TypeSpec)], arguments: &[(Identifier, TypeSpec)],
@ -571,7 +571,7 @@ impl Builder {
None => { None => {
let return_type = context.unknown_type(location.clone()); let return_type = context.unknown_type(location.clone());
let method = Method::new( let method = Method::new(
method_name.clone(), method_name,
return_type, return_type,
parent_type.clone(), parent_type.clone(),
modifier, modifier,
@ -598,15 +598,13 @@ impl Builder {
method.push_clause(arguments, block_idx, result_type); method.push_clause(arguments, block_idx, result_type);
} }
fn env_set(&mut self, name: &StringIdx, ty: &TyIdx) { fn env_set(&mut self, name: StringIdx, ty: &TyIdx) {
self.peek_block_mut() self.peek_block_mut().unwrap().env_set(name, ty.clone());
.unwrap()
.env_set(name.clone(), ty.clone());
} }
fn env_get(&self, name: &StringIdx) -> Option<&TyIdx> { fn env_get(&self, name: StringIdx) -> Option<&TyIdx> {
for block in self.blocks.iter().rev() { for block in self.blocks.iter().rev() {
if let Some(idx) = block.env_get(name.clone()) { if let Some(idx) = block.env_get(name) {
return Some(idx); return Some(idx);
} }
} }
@ -657,10 +655,10 @@ impl Builder {
self.types.pop() self.types.pop()
} }
fn prop_ty(&self, name: &StringIdx, context: &Context) -> Option<TyIdx> { fn prop_ty(&self, name: StringIdx, context: &Context) -> Option<TyIdx> {
for ty_idx in self.types.iter().rev() { for ty_idx in self.types.iter().rev() {
let ty = context.get_type(ty_idx).unwrap(); let ty = context.get_type(ty_idx).unwrap();
let p = ty.get_prop_type(&name); let p = ty.get_prop_type(name);
if p.is_some() { if p.is_some() {
return Some(p.unwrap().clone()); return Some(p.unwrap().clone());
} }

View file

@ -4,11 +4,11 @@ use string_interner::{StringInterner, Sym};
pub struct StringTable(StringInterner<Sym>); pub struct StringTable(StringInterner<Sym>);
impl StringTable { impl StringTable {
pub fn get(&self, idx: &StringIdx) -> Option<&str> { pub fn get(&self, idx: StringIdx) -> Option<&str> {
self.0.resolve(idx.into()) self.0.resolve(idx.into())
} }
pub fn intern(&mut self, value: &str) -> StringIdx { pub fn intern<T: Into<String> + AsRef<str>>(&mut self, value: T) -> StringIdx {
self.0.get_or_intern(value).into() self.0.get_or_intern(value).into()
} }
@ -18,7 +18,7 @@ impl StringTable {
} }
} }
#[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord)] #[derive(Debug, Clone, PartialEq, PartialOrd, Eq, Ord, Copy)]
pub struct StringIdx(Sym); pub struct StringIdx(Sym);
impl From<Sym> for StringIdx { impl From<Sym> for StringIdx {
@ -63,6 +63,6 @@ mod test {
fn test_get() { fn test_get() {
let mut stable = StringTable::default(); let mut stable = StringTable::default();
let idx = stable.intern("Marty McFly"); let idx = stable.intern("Marty McFly");
assert_eq!(stable.get(&idx).unwrap(), "Marty McFly"); assert_eq!(stable.get(idx).unwrap(), "Marty McFly");
} }
} }

View file

@ -27,9 +27,9 @@ impl Ty {
self.location.as_ref() self.location.as_ref()
} }
pub fn get_prop_type(&self, name: &StringIdx) -> Option<&TyIdx> { pub fn get_prop_type(&self, name: StringIdx) -> Option<&TyIdx> {
match self.inner { match self.inner {
TyInner::Type { ref properties } => properties.get(name), TyInner::Type { ref properties } => properties.get(&name),
_ => None, _ => None,
} }
} }
@ -159,7 +159,7 @@ impl Ty {
} }
pub fn name(&self) -> Option<StringIdx> { pub fn name(&self) -> Option<StringIdx> {
self.name.clone() self.name
} }
pub fn new_impl(ty: TyIdx, tr: TyIdx, location: Location) -> Ty { pub fn new_impl(ty: TyIdx, tr: TyIdx, location: Location) -> Ty {