compiler

package
v0.0.0-...-e8ad6af Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Sep 12, 2026 License: BSD-3-Clause Imports: 10 Imported by: 0

Documentation

Overview

Package compiler lowers the AST to bytecode (an ISeq tree).

Each method body and the program top level becomes one ISeq. Locals are resolved to flat slot indices here (Phase 0 has no closures, so each ISeq has a single flat local table; depth-addressed envs arrive with blocks in Phase 1, plan §6).

The flip-flop operator: a two-sided range literal written where a condition is expected (`x if (i == 4)..(i == 7)`). It is not a Range object but a piece of state that turns on when the left condition holds and off after the right one does — awk's and sed's range addressing.

MRI's parser marks such a range NODE_FLIP2 (`..`) or NODE_FLIP3 (`...`) by its syntactic position, and compile.c's compile_flip_flop (ruby/ruby v3_4_0:4607) lowers it against a per-occurrence slot allocated in the enclosing *local* iseq — ISEQ_FLIP_CNT_INCREMENT(ISEQ_BODY(iseq)->local_iseq) — so a block shares its state with every other invocation of that block, and two textually identical flip-flops in different iseqs do not interfere.

The generated sequence is MRI's, with one difference: MRI compiles it straight into the surrounding branch's then/else labels, while rbgo's conditions are ordinary values that the caller branches on, so this pushes true or false instead. rbgo's local slots are already depth-addressed and resolution stops at the first non-block scope, which is exactly MRI's local_iseq, so a slot allocated there has the lifetime the operator needs.

Compound assignment to an index (`a[i] op= v`) and to an attribute (`a.x op= v`), lowered so the receiver and the index arguments are evaluated exactly once and the expression's value is the assigned value — never what the `[]=` / `x=` setter happens to return.

The parser desugars both forms textually: `a[i] op= v` arrives as `a.[]=(i, a.[](i) op v)` and `a.x op= v` as `a.x=(a.x op v)`, with the receiver and index nodes SHARED (same AST pointers) between the read and the write. That shape is correct for value but wrong for effect: compiled literally it evaluates the receiver twice and every index argument twice. MRI does not: compile.c's compile_op_asgn1 evaluates the receiver and index once and reuses them with `dupn` (ruby/ruby v3_4_0 compile.c:9401), and compile_op_asgn2 does the same for an attribute with `dup` (compile.c:9535). Both then overwrite the reserved result slot with `setn`, so the expression yields the right-hand value (or, when `||=` / `&&=` short-circuits, the value already there).

rbgo's stack has no `dupn`/`setn`/`topn`, so the same effect is obtained with anonymous local slots as temporaries.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Compile

func Compile(prog *ast.Program) (iseq *bytecode.ISeq, err error)

Compile lowers a Program into the top-level ISeq, treating string literals as UTF-8 (the default source encoding).

func CompileWithEncoding

func CompileWithEncoding(prog *ast.Program, srcEnc string) (iseq *bytecode.ISeq, err error)

CompileWithEncoding lowers a Program whose source declared srcEnc (a canonical encoding name, or "" for UTF-8) via a `# encoding:` magic comment, so string literals carry that encoding.

func CompileWithLocals

func CompileWithLocals(prog *ast.Program, localNames []string) (iseq *bytecode.ISeq, err error)

CompileWithLocals lowers prog for a Binding eval: it compiles in a child scope whose parent holds the binding's locals (by slot), so references to them resolve at depth 1 — reads and writes reach the binding's environment when the ISeq is run with that environment as the parent — while any new locals are scratch in the child frame.

func MagicSourceEncoding

func MagicSourceEncoding(src string) string

MagicSourceEncoding returns the canonical registry encoding name declared by a `# encoding:` / `# coding:` magic comment on the first line of src (or the second when the first is a shebang), or "" for UTF-8 or no declaration. Only the encodings the negotiation cares about are recognised by canonical spelling; anything else (including plain UTF-8) yields "" so literals keep the default.

Types

type Compiler

type Compiler struct {
	// contains filtered or unexported fields
}

Compiler walks the AST, maintaining a stack of builders.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL