diff --git a/spec/chip.typ b/spec/chip.typ index d207cec8f..713f39b87 100644 --- a/spec/chip.typ +++ b/spec/chip.typ @@ -26,27 +26,82 @@ /// Generates a table listing `chip`'s columns. #let render_chip_column_table(chip, config) = { + + // Render a definition's range + let render_def_range(idx, range) = { + if type(range) == array { + if range.len() == 1 { + [#raw(idx) `=` #range.at(0)] + } else if range.len() == 2 { + [#raw(idx) #sym.in `[`#range.at(0)`,`#range.at(1)`]`] + } else { + assert(false, message: "invalid range: " + repr(range) + repr(range.len())) + } + } else { + [#raw(idx) `=` #range] + } + } + + // Render definition `def` + let render_definition(def, var_name) = { + if type(def) in (array, str) { + return ( + [], + table.cell(align: right, emph[definition]), + table.cell(colspan: 2, expr_to_math(def)) + ) + } + + assert(type(def) == dictionary, message: "invalid definition: " + repr(def)) + + if "poly" in def { + ( + [], + table.cell(align: right, emph[definition]), + expr_to_math((":=", ("idx", var_name, def.idx), def.poly)), + render_def_range(def.idx, def.range) + ) + } else if "polys" in def { + ( + [], + table.cell(align: right, emph[definition]), + table.cell(colspan: 2, expr_to_math(("idx", var_name, def.idx))) + ) + for (i, poly) in def.polys.enumerate() { + ( + [], + [], + expr_to_math((":=", " ", poly.poly)), + render_def_range(def.idx, poly.range), + ) + } + } else { + assert(false, message: "invalid definition: " + repr(def)) + } + } + // Group variables by category show figure: set block(breakable: true) figure(table( - columns: (auto, auto, 1fr), + columns: (auto, auto, 1fr, auto), inset: 6pt, align: left + top, stroke: none, - table.header([*Label*], [*Type*], [*Description*]), + table.header([*Label*], [*Type*], table.cell(colspan: 2, [*Description*])), table.hline(stroke: stroke(thickness: 2pt)), ..for (cat, vars) in chip.variables.pairs() { - ([#emph(cat)], [], [], table.hline(stroke: .6pt)) + (table.cell(colspan: 4, emph(cat)), table.hline(stroke: .6pt)) for var in vars { - ([#raw(var.name)], [#type_to_code(var.type)], [#eval(var.desc, mode: "markup")]) - for (i, poly) in var.at("polys", default: ()).enumerate() { - (if i == 0 { emph[def] }, [], expr_to_math(("=", ("idx", var.name, i), poly))) - } - if "poly" in var { - (emph[def], [], expr_to_math(var.poly)) + ( + [#raw(var.name)], + [#type_to_code(var.type)], + table.cell(colspan: 2, [#eval(var.desc, mode: "markup")]) + ) + if "def" in var { + render_definition(var.def, var.name) } } - ([], [], []) + (table.cell(colspan: 4, []), ) }, ), caption: [Column overview of #chip.name chip.]) } diff --git a/spec/expr.typ b/spec/expr.typ index c005e5a35..ae7bd0792 100644 --- a/spec/expr.typ +++ b/spec/expr.typ @@ -55,7 +55,7 @@ "add": 6, // + "sub": 7, // - "idx": 8, // [] - "eq": 9, // = + "eq": 9, // = and := "MAX": 10, // ) @@ -100,6 +100,7 @@ rec(PREC.pow, e.at(1)) + `^` + rec(PREC.pow, e.at(2)) }, "=": (pp, rec, e) => rec(PREC.eq, e.at(1)) + ` = ` + rec(PREC.eq, e.at(2)), + ":=": (pp, rec, e) => rec(PREC.eq, e.at(1)) + ` := ` + rec(PREC.eq, e.at(2)), "-": (pp, rec, e) => { if e.len() == 2 { // Negation @@ -138,6 +139,7 @@ $#e.at(1)^#e.at(2)$ }, "=": (pp, rec, e) => $#rec(PREC.eq, e.at(1)) = #rec(PREC.eq, e.at(2))$, + ":=": (pp, rec, e) => $#rec(PREC.eq, e.at(1)) := #rec(PREC.eq, e.at(2))$, "-": (pp, rec, e) => { if e.len() == 2 { // Negation diff --git a/spec/src.typ b/spec/src.typ index 75a81a5f9..7c9e68487 100644 --- a/spec/src.typ +++ b/spec/src.typ @@ -38,8 +38,18 @@ assert(category in config.variables.categories.all) } + // Check that `def` is only contained in `virtual` variables + let non_virtual_vars = chip.variables.pairs().filter(x => x.first() != "virtual").map(x => x.last()).flatten(); + for var in non_virtual_vars { + assert( + "def" not in var, + message: "illegal `def` in non-virtual var: " + repr(var.name) + ) + } + + let all_vars = chip.variables.values().flatten() let all_labels = config.variables.types.map(type => type.label); - for var in chip.variables.values().flatten() { + for var in all_vars { let type_label = if type(var.type) == array { var.type.at(0) } else {