Types And Property Resolution

type {} captures the current context and creates (behaves like?) a nested context.

Accessing a reference inside a type

  1. check for property on the type
  2. check for property on any super type
  3. check for reference in current context (which may include a wrapping type)

Accessing a property on a type

  1. check for property on the type
  2. check for property on any super type
add = -> (a<System.Integer>, b<System.Integer>) {
	a + b
}

subtract = -> (aa<System.Integer>, bb<System.Integer>) {
	aa - bb
}

User = type {
	# `name` is an instance property, defined on the type's prototype
	@.name = -> { :Thomas }

	# `add` resolves to `User.add`, even when called on an instance of `Administrator`
	# this is due to lambdas being lexically scoped
	# would it be better to force resolution to the module `add` above?
	@.age1 = -> { add(12, 13) }

	# `@` resolves to the lambda's receiver, which in this case will be an instance of `User` or `Administrator`
	# `add` resolves to `User.add`, defined below
	@.age2 = -> { @.type.add(12, 13) }

	# `subtract` resolves to module-level function above
	add = -> (foo<System.Integer>, bar<System.Integer>) {
		subtract(22, 12) + foo + bar
	}

	# `@` is the lambda's receiver, in this case `User`
	# `@` will resolve to `Administrator` when referenced below in `Administrator.other`
	# `add` resolves to `User.add` or `Administrator.add`, depending on how `create` is accessed
	create = -> {
		@.add(1, 2)
	}

	# `self` in a type is a reference to the type
	the_type = self
}

# types can inherit from multiple types
# internally ancestors are flattened into a normalized list of ancestors
# all types inherit from `System.Object`, which is always the last ancestor in the list
Administrator = type (User) {
	# `name` is an instance property, defined on the type's prototype
	@.name = -> { :Allea }

	# `subtract` resolves to module-level function above
	add = -> (idk<System.Integer>, hero<System.Integer>) {
		subtract(42, 2) + User.add(idk, hero)
	}

	# `@` is the lambda's receiver, in this case `Administrator`
	# `create` resolves to `User.create` as `Administrator` inherited from `User`
	other = -> { @.create() }

	# `Administrator.alias` references the same property as `Administrator.create`, which is inherited from `User`
	alias = create

	# `the_type` is an inherited reference to `User`
	the_sub_type = the_type

	# `User` resolves because `Administrator` is defined in the same context as `User`, *not* because `User` is an ancestor
	aaaa = User.create()

	# call `Administrator.add` defined above
	bbbb = add()

	# all constructs are available inside a type (or lambda)
	cccc = if (aaaa == bbbb) {
		'cccc is true'
	} else {
		'cccc is false'
	}
}