titan-lang / titan

The Titan programming language
http://titan-lang.org
MIT License
406 stars 13 forks source link

Records with methods #201

Closed mascarenhas closed 6 years ago

mascarenhas commented 6 years ago

The purpose of this WIP PR is to complete the implementation of records, with a couple of extras that enrich records to be a stepping stone if we decide to add true classes later on. The idea is that records can have methods, declared with Lua-like syntax:

record Point
  x: float
  y: float
end

function Point:move(dx: float, dy: float)
  self.x = self.x + dx
  self.y = self.y + dy
end

local function example()
  local p: Point = { x = 2, y = 3 }
  p:move(3, 4)
end

There will be no inheritance, so no subtyping relation between these records, and no need for vtables: a method call through a record type is resolved statically.

The PR also will add the ability to reference record types from imported modules through qualified type names, such as mod.Point, where the first part of the qualified name is the local name given to the imported module.

A record value passed to a dynamic context should have a metatable that allows it to be accessed from Lua as a regular object, as well as a tag for dynamic type checks. A record is then a dual object: on the Titan side it is just a fixed-size vector of slots (represented with a CClosure), while from the Lua side (or when stored in an array, or cast to value) it is a userdata with a type tag and a metatable. The closure and userdata point to each other.

codecov-io commented 6 years ago

Codecov Report

Merging #201 into master will decrease coverage by 0.11%. The diff coverage is 92.93%.

Impacted Files Coverage Δ
titan-compiler/driver.lua 73.83% <100%> (+1.55%) :arrow_up:
titan-compiler/symtab.lua 89.47% <100%> (+0.28%) :arrow_up:
titan-compiler/parser.lua 96.32% <100%> (+0.38%) :arrow_up:
titan-compiler/syntax_errors.lua 100% <100%> (ø) :arrow_up:
titan-compiler/ast.lua 100% <100%> (ø) :arrow_up:
titan-compiler/checker.lua 90.61% <86%> (-3.49%) :arrow_down:
titan-compiler/types.lua 85.49% <91.02%> (+0.87%) :arrow_up:
titan-compiler/coder.lua 96.39% <98.97%> (+1.47%) :arrow_up:

Continue to review full report at Codecov.

Legend - Click here to learn more Δ = absolute <relative> (impact), ø = not affected, ? = missing data Powered by Codecov. Last update 8cff201...2a8b843. Read the comment docs.

mascarenhas commented 6 years ago

This is close to done, the major feature missing is to populate the metatable that allows the Lua side to use records effectively, as well as writing documentation. Another must have is the new function for records, right now only the table constructor works.

A nifty feature is the reverse map from tags to record type names that is kept on the registry, so miscasts from a value holding a record value to an incompatible record type report the two record types. It will be nice to later extend this to miscasts from a value holding a record to other types.

mascarenhas commented 6 years ago

Ok, this BIG addition is now good to go. There is a new "shadow" node type in the AST for record functions so I could implement new without special-casing it, but the parser has not been extended to let the user define these functions; the semantic action for records synthesizes a record function node for new with a body that uses a regular record constructor ({ fields }).

All the typechecker/codegen plumbing is in place if we want to add those functions, though, it is just a matter of adding a new rule to the parser.