Skip to content
Snippets Groups Projects
Unverified Commit 075c7af5 authored by Yorick Peterse's avatar Yorick Peterse
Browse files

Move std::trait.implement to Trait.implement

This removes the need for importing std::trait in every module. The
resulting API is also less awkward to use.
parent 457706e1
No related branches found
No related tags found
No related merge requests found
Loading
Loading
@@ -470,13 +470,12 @@ module Inkoc
 
def implement_trait(object, trait, body, location)
message = Config::IMPLEMENT_TRAIT_MESSAGE
trait_mod = get_global(Config::INTERNAL_TRAIT_IMPORT, body, location)
method = trait_mod.type.lookup_method(message).type
method = trait.type.lookup_method(message).type
 
send_object_message(
trait_mod,
trait,
message,
[object, trait],
[object],
[],
method,
method.return_type,
Loading
Loading
Loading
Loading
@@ -20,7 +20,6 @@ module Inkoc
@module.imports << import_bootstrap(loc) if @module.import_bootstrap?
@module.imports << import_globals(loc) if @module.import_globals?
@module.imports << import_prelude(loc) if @module.import_prelude?
@module.imports << import_trait(loc) if @module.import_trait_module?
end
 
# Generates the import statement for importing the bootstrap module.
Loading
Loading
@@ -74,14 +73,6 @@ module Inkoc
AST::Import.new([core, prelude], [symbol], location)
end
 
def import_trait(location)
import_std_module_as(
Config::TRAIT_MODULE,
Config::INTERNAL_TRAIT_IMPORT,
location
)
end
def import_std_module_as(name, symbol_name, location)
std = identifier_for(Config::STD_MODULE, location)
name_ident = identifier_for(name, location)
Loading
Loading
Loading
Loading
@@ -81,10 +81,6 @@ module Inkoc
name.to_s != Config.core_module_name(Config::BOOTSTRAP_MODULE)
end
 
def import_trait_module?
import_prelude?
end
def source_code
location.file.path.read
end
Loading
Loading
Loading
Loading
@@ -6,47 +6,44 @@ let Trait = Inko::Trait
# The name of the attribute that stores all the implemented traits.
let IMPLEMENTED_TRAITS_ATTRIBUTE = '@_implemented_traits'
 
# Implements a `Trait` for an `Object`.
#
# Implementing a trait will result in all the trait's methods being copied over
# to the given object. Once copied, the trait is tracked in an internal object
# so modules such as `std::mirror` can reflect upon this data during runtime.
#
# This method is not really meant for general use, instead it's called by the
# compiler whenever implementing a trait using the `impl` keyword.
#
# # Examples
#
# Manually implementing a trait, ignoring any required methods:
#
# # `trait` is a keyword, so we must define a custom alias for the module.
# import std::trait::(self as trait_mod)
#
# trait MyTrait {
# def number -> Integer {
# 42
# }
# }
#
# object Person {}
#
# trait_mod
# .implement(implement_for: Person, to_implement: MyTrait) # => MyTrait
#
# Person.new.number # => 42
def implement(implement_for: Object, to_implement: Trait) -> Trait {
# This will look up `@_implemented_traits` if it exists, or create it (then
# return it) if it does not.
let mut traits =
_INKOC.set_attribute_to_object(implement_for, IMPLEMENTED_TRAITS_ATTRIBUTE)
impl Trait {
# Implements a `Trait` for an `Object`.
#
# Implementing a trait will result in all the trait's methods being copied
# over to the given object. Once copied, the trait is tracked in an internal
# object so modules such as `std::mirror` can reflect upon this data during
# runtime.
#
# This method is not really meant for general use, instead it's called by the
# compiler whenever implementing a trait using the `impl` keyword.
#
# # Examples
#
# Manually implementing a trait, ignoring any required methods:
#
# trait MyTrait {
# def number -> Integer {
# 42
# }
# }
#
# object Person {}
#
# MyTrait.implement(Person) # => MyTrait
# Person.new.number # => 42
static def implement(implement_for: Object) -> Trait {
# This will look up `@_implemented_traits` if it exists, or create it (then
# return it) if it does not.
let traits =
_INKOC.set_attribute_to_object(implement_for, IMPLEMENTED_TRAITS_ATTRIBUTE)
 
_INKOC.copy_blocks(implement_for, to_implement)
_INKOC.copy_blocks(implement_for, self)
 
# This marks the Trait as implemented by storing the Trait as an attribute,
# with its value set to True. We can not use other data structures such as
# `std::map::Map`, since they may not yet exist when this method is
# used.
_INKOC.set_attribute(traits, to_implement, True)
# This marks the Trait as implemented by storing the Trait as an attribute,
# with its value set to True. We can not use other data structures such as
# `std::map::Map`, since they may not yet exist when this method is used.
_INKOC.set_attribute(traits, self, True)
 
to_implement
self
}
}
Loading
Loading
@@ -162,7 +162,7 @@ test.group('std::mirror::ObjectMirror.implements_trait?') do (g) {
let obj = Dummy.new
let mirror = ObjectMirror.new(obj)
 
trait_mod.implement(implement_for: obj, to_implement: Trait2)
Trait2.implement(obj)
 
assert.true(mirror.implements_trait?(Trait1))
assert.true(mirror.implements_trait?(Trait2))
Loading
Loading
Loading
Loading
@@ -9,12 +9,12 @@ trait Example {
}
}
 
test.group('std::trait.implement') do (g) {
test.group('std::trait::Trait.implement') do (g) {
g.test('Copying the default methods of a Trait to the Object') {
let obj = Object.new
let obj_mirror = mirror.reflect_object(obj)
 
trait_mod.implement(implement_for: obj, to_implement: Example)
Example.implement(obj)
 
let method_impl = obj_mirror.get_attribute('pass') as Block
let method_exp =
Loading
Loading
@@ -27,7 +27,7 @@ test.group('std::trait.implement') do (g) {
let obj = Object.new
let obj_mirror = mirror.reflect_object(obj)
 
trait_mod.implement(implement_for: obj, to_implement: Example)
Example.implement(obj)
 
assert.equal(obj_mirror.implemented_traits, Array.new(Example))
}
Loading
Loading
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment