Skip to content

Releases: zilch-lang/nstar

N* v2.2.0

13 Apr 20:30
8a9d1d5
Compare
Choose a tag to compare

✨ What's new?

  • It is now possible to link against symbols that should be statically present at link-time using the extern.code section
    Each binding is given a type that should correspond to the underlying FFI type, but this cannot be checked
  • Bang-types have made it into N*!
    These are used to forget about some register binding
    However, “forget” means different things depending on where the bang-type lies:
    • If the bang-type is in the caller's context, then this means that upon returning from this function, the register associated to the bang-type cannot be trusted anymore
      This allows for some kind of reminder as to which register has to be callee-saved
    • If the bang-type is in the continuation, then this means that we basically don't care about the previous value in a register, and that we may even plan on overwriting it
  • String literals are also a thing now, which makes it easier to write a basic "hello, world!" example
  • A new sref n, r instruction was born, to be able to fetch a reference to a stack cell
  • And finally, packed structures with their literal equivalents for the data sections

  • And as a side note, a small emacs mode was written just to provide syntax highlighting for N* code:
    image

🐛 Bug fixes

  • sst r, n was compiled to the wrong opcodes when targeting amd64
  • When type-checking the mv instruction, when it moved the continuation, the register environment χ was not extended with the correct type (the ∀(). part was erased)

N* v2.1.0

22 Mar 10:57
baa3c09
Compare
Choose a tag to compare

🎉 Additional features

  • include sections allow to include code from other files found in the include path
    • Those cannot be cyclic, i.e. you cannot include X in Y if you already included Y in X
    • It is impossible to include the same file multiple times. If you are familiar with C or C++, that's what header guards are for, but they are completely implicit here!
    • Includes work using an include path, which is simply a set of path to search in. The include path always contains at least the current directory, but can be extended using the -I <PATH> (or -I=<PATH>) flag
    • A simple example of including files can be found in the examples directory, namely the true.nst file

🐛 Some bug fixes

  • a bug in the ELF object generation library causing a crash has been fixed. This was triggered when the current file didn't include global symbols (for now, all functions in the code section are marked as global).

N* v2.0.0

15 Mar 14:24
171869a
Compare
Choose a tag to compare

This second version of N* is a major improvement over the first one. 🎉

🚫 Some of the problems of the first version

  1. in the first version, the branch-checker was something needed to ensure we did not break the control flow
  2. code addresses could not be manipulated as it would have made the branch-checker meaningless
  3. because of how context types were handled, writing {} was allowed but should not have been a correct context because it does not contain a stack (%sp not bound)
  4. the first version is heavily oriented towards the amd64 architecture
  5. instructions were not attached to a specific label, requiring the branch-checker to make the type-checking stage correct (it did not treat label fallthrough, as per #12)
  6. some bugs in the ELF file generation library were later discovered (e.g. the sh_info field of the .symtab section was not assigned the correct value sometimes)

ℹ️ How those problems have been addressed in the second version

  1. the control flow is now simply controlled by the fact that every block ends with a jumping (“terminal”) instruction: call, jmp or ret
    the branch-checker was therefore made useless, and has completely been removed
  2. because instructions are now scoped, and thanks to the introduction of continuations (discussed below), we can “safely” manipulate code addresses within N*
  3. the new context type, written ∀(v).{ χ | σ → ε }, now requires a stack σ
  4. instructions have been made more abstract, allowing to target any architecture more easily
  5. the syntax of label bindings has been a little bit reworked, leading to label: type = block where the instruction block is now scoped to the label
  6. those bugs have been fixed

✨ Added features that were not in the first version

  • continuations might be the biggest added feature there
    basically, continuations allow for safe jumps where the return address (in case of a call) is fully known at compile-time and cannot be changed at all
    ⚠️ continuations did exist in the first version, but under a different form where the compiler would try to infer the return context (this is not the case anymore in the second version because continuations are explicitly typed)
  • the new context types now embed the expected stack as well as the expected continuation
    for example, writing f: forall(s: Ts, e: Tc).{ %r5: forall().{| s -> e } | s -> %r5 } means that we can jump (or call) to f only if the current environment contains a function pointer in %r5, which is used as the continuation function when returning from f
    the continuation cannot be overwritten nor replaced (this is checked by the compiler)
  • the grammar has been reworked a little bit:
    • the unsafe qualifier now applies only to specific instructions, not anymore to blocks of instructions (this is to greatly reduce the added complexity of parsing unsafe blocks within instruction blocks)
    • binders now accept a simple = sign between their type and their value
      this is mainly done to simplify scoping rules (writing x: u64 0 1 was allowed and checked by the compiler ─ now this is forbidden by the grammar, requiring no more internal checks)
    • an instruction block is a list of instructions separated by ;, and ended by a terminal instruction (one of jmp, call or ret)
      this restriction only makes sure that it is impossible to use one of the terminal instructions in the middle of an instruction block
  • the instruction set has completely been reworked to abstract away some architecture details (leaning towards amd64) and highly simplify inference rules and type-checking
    all the new instructions are described in the specification document (it would be too long to describe them all here)
  • N* code is now compiled into a small abstract machine core (the NSAM) which is later compiled for the target architecture (may it be some machine code, or even bytecode for a virtual machine)

N* v1.0.0

20 Jan 22:40
4c1fcc2
Compare
Choose a tag to compare
N* v1.0.0 Pre-release
Pre-release

Finally!

The first version of N* is finally finished.
The compiler incorporates the following features:

  • code and data sections
    • the code section contains a sequence of labels and instructions
    • the data section contains a sequence of named values (where each label is associated with a value)
  • Instructions:
    • push expr
      • ✅ Completely parses
      • ✅ Completely type-checks
      • Only compiles when expr is an immediate integer or a register
    • pop expr
      • ✅ Completely parses
      • Only type-checks when expr is a register (from %r0 to %r5)
      • Compiles when expr is a register
    • nop
      • ✅ Completely parses
      • ✅ Completely type-checks
      • ✅ Completely compiles
    • jmp label
      • ✅ Completely parses
      • ✅ Completely type-checks
      • ✅ Completely compiles to a 32-bit %ip displacement
    • call label
      • ✅ Completely parses
      • ✅ Completely type-checks
      • ✅ Completely compiles to a 32-bit %ip displacement
    • ret
      • ✅ Completely parses
      • ✅ Completely type-checks
      • ✅ Completely compiles
    • mov src, dst
      • ✅ Completely parses
      • Only type-checks when src and dst aren't pointer offsets
      • Only compiles when src and dst aren't some sort of pointer offsets
  • Compilation only targets ELF64 (ELF 64-bit relocatable file; needs to be compiled with the C runtime etc)
  • unsafe blocks are used to enclose potentially unsafe instruction blocks

Expect more to come in the next months! Some expression types are not yet handled in the type-checker, or even the code generation step.