Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Generating Code

A meta function can take the code being compiled as a List, inspect it, and return new code for the compiler to insert. Read Compile-time Macros first. The macro declares what code to capture; the meta function implements the transformation in x2c. Include meta.x to use the compiler’s operations: the methods of Code and Type, and the x2c_ helpers.

Calling a meta function from a macro body

A macro body can call a meta helper with $helper(args). Passing a captured hole directly supplies its code to the helper; it does not evaluate the future runtime expression. This form works for code transformations such as the field query below. Complete captures also retain their source information for text and location queries; constructed subtrees do not acquire it.

#include "x2c.x"
#include "meta.x"

typedef struct Point { int x, y, z; } Point;

meta static List field_count(TypeInfo type) =>
  $!int{ ${((List) type.assoc(<fields>)).len()} };

macro Expression $probe.count(Expr $value) => $field_count($value);

int main(void) {
  Point p = { 1, 2, 3 };
  printf("count %d\n", $probe.count(p));
  return 0;
}
count 3

The macro body is one call and nothing else. That is the usual shape: the macro declares the holes and the result kind, and the meta function does the work.

field_count declares its parameter TypeInfo, so it receives a description of the argument’s type rather than its code. The compiler computes that description at the $ call:

((name "Point") (kind struct) (type ("Point"))
 (fields (("x" (int)) ("y" (int)) ("z" (int)))) (methods ()))

name is the type’s name, or "" when it has none. kind is struct, union, enum, pointer, scalar or other. type is the canonical type, and fields lists the (name type) rows of a struct or union’s named fields in declaration order. methods lists the names of the type’s direct dotted methods. Read a part with List.assoc. Pass the same hole twice when a function needs both the code and its type, as shape_reads does below.

The function’s result determines the expansion. A List that a quotation built represents code. A typed quotation of one value, such as $!int{ $count } or $!String{ $name }, is an expression holding that value.

A Stmt macro can use the same arrow form. Its body is then the statement $helper(args);, and the helper may return any statement that fits where the macro is invoked, not only an expression:

#include "x2c.x"
#include "meta.x"

meta static List repeated(List code) => %(block $code $code);

macro Stmt $sample.twice(Stmt $code) => $repeated($code);

int main(void) {
  int n = 0;
  $sample.twice(n += 2;);
  $sample.twice(if (n == 4) puts("four"););
  printf("%d\n", n);
  return 0;
}
four
four
4

repeated receives each captured statement as code and returns a block that holds it twice. The second invocation passes an if statement, which an expression position could not accept. A $helper(args); statement in an ordinary function may also return a statement. There, only an expression node, a macro application, a quotation, or an identifier is code. A %(block ...) such as the one repeated builds is data there and becomes a runtime List value. A helper for ordinary code therefore returns statements as a $!{ ... } quotation.

Methods, source text, and embedded files

A TypeInfo parameter’s methods part lists the type’s direct dotted methods. A generator can test for one and build the dotted call, which the compiler resolves as it would the same call in source:

#include "meta.x"
meta static List project_write(TypeInfo type, List receiver, List value) {
  List methods = type.assoc(<methods>);
  if (!methods.contains("write")) return %();
  return $!( $receiver.write($value) );
}

The list does not search delegate fields. A delegated result would also need the field-projected receiver, which this operation does not return. Generated dotted calls still use delegation during ordinary expression resolution.

To read the exact source text of a complete captured argument, declare the parameter Source and use Code.source_text:

#include "meta.x"
meta static String project_text(Source value) => Code.source_text(value);
macro Expression $project.source(Expr $value) => $project_text($value);

int main(void) {
  return strcmp($project.source(1 /* kept */ + 2),
                "1 /* kept */ + 2");
}

Passing a complete capture to a meta helper preserves the source information for this query. Forwarding it through another source macro does too. Constructing or selecting an AST subtree does not invent source text; use List.repr() to render code data.

x2c_embed_text reads a regular text file into a compile-time String and records it as a build dependency. A captured String literal retains the caller’s file location for resolving a relative path:

#include "meta.x"
meta static String project_notice(Source path) => x2c_embed_text(path);
macro Expression $project.notice(Literal $path) => $project_notice($path);

String notice = $project.notice("notice.txt");

A captured path stays relative to its caller even when the macro is defined in an imported file. A project meta function also accepts an absolute String path; a relative one needs the Source that locates it.

Empty files are valid. Directories, embedded NUL bytes, unreadable files and files too large for a String are rejected.

Source templates from meta functions

A Unit or Stmt macro used as an expression inside a meta function constructs a deferred template invocation. Its arguments are values computed by the meta function. The returned code expands when inserted into the program, using ordinary macro substitution, scope and binding rules. Expression macros retain their usual expansion behavior.

macro Unit $sample.make_function(Name $name, Expr $result) {
  int $name(void) { return $result; }
}

meta static List build_function(String name, int n) {
  List node = $sample.make_function(name, n * 2);
  return %($node);
}

macro Unit $sample.make_answer() { @build_function("answer", 21) }

$sample.make_answer();
int main(void) {
  printf("%d\n", answer());
  return 0;
}
42

The constructor returns one code node. The helper wraps it in a List because @ inserts a sequence of nodes. It does not return an already expanded function declaration for the helper to inspect. Name, Type, parameter and statement captures still follow the source macro’s declared hole kinds.

A decorator can make that choice from the function it captures. Here the meta helper selects one of two named Stmt templates, then the decorator inserts the selected invocation into the function body:

#include "x2c.x"
#include "meta.x"

static int calls = 0;

macro Stmt $sample.counted(Stmt @body) {
  calls++;
  @body
}

macro Stmt $sample.plain(Stmt @body) {
  @body
}

meta static List choose_body(List function) {
  List body = Code.body(function);
  String name = Code.name(function);
  List node = name == "tracked" ? $sample.counted(body) : $sample.plain(body);
  return %($node);
}

macro Decorator $sample.count_if_tracked(Function $function) {
  @choose_body($function)
}

$sample.count_if_tracked()
static int tracked(void) { return 7; }

$sample.count_if_tracked()
static int ordinary(void) { return 9; }

int main(void) {
  printf("%d %d %d\n", tracked(), ordinary(), calls);
  return 0;
}
7 9 1

choose_body runs while the compiler expands the decorator. It reads the captured function, computes the choice, and returns a deferred invocation. The chosen template expands when the returned code is inserted. Its body capture becomes the function’s statements; calls++ runs only when tracked is called at runtime. The template names are known in source, while meta chooses which one to use for each function.

The reverse gradient generator in packages/autodiff/src/autodiff-macros.x uses this pattern. Its ad_reverse_with returns an invocation of the ad.gradient source macro. The macro contains the generated function declaration, tape storage, reverse-pass label and cleanup. Meta helpers compute the parameter and statement sequences. The macro owns the fresh scratch names and passes those same names to the fragment helpers, keeping all generated references in the intended function scope.

Quoting code with $!

A template that a meta function uses once can be written where it is used. $!( expression ) builds an expression, $!{ items } builds statements, and $!Unit{ ... }, $!Field{ ... }, or another category name before the braces builds that kind of code. A $name inside refers to the function’s local name and inserts its value: syntax where the position takes syntax, and a number, String, or Symbol as a literal. @name splices a List local. ${expression} inserts any value; see below. Each local’s first position determines what it fills.

#include "x2c.x"
#include "meta.x"

meta static List numbered(List subject, List arms) {
  Array cases = [];
  int index = 0;
  foreach (List arm, arms) {
    cases.push($!{ if ($subject == $index) $arm });
    index++;
  }
  return cases.list_free();
}

macro Stmt $sample.choose(Expr $subject, Stmt @arms) {
  @numbered($subject, $arms)
}

int main(void) {
  int pick = 1;
  $sample.choose(pick, printf("zero\n");, printf("one\n");, printf("two\n"););
  return 0;
}
one

A quotation is an anonymous macro applied at once to the locals its body names, so it follows the same rules as any template: arguments arrive as the syntax or values the locals hold, names the body declares are private to the expansion, and other names resolve where the code lands. It keeps nothing from the function once it has been applied. Inside a %(...) List, $ inserts a value, so bind a quotation to a local first and insert the local. $ inserts one value and @ splices a sequence in templates and quotations. Runtime List literals use the same prefixes. Native C varargs retain their ... spelling. An @name sequence splices into call arguments and braced initializers such as $!( { @items } ) or (T){ $first, @rest }, and %[@items] Array literals; Map entries splice as %{${@rows}}. A quotation expands where code is bound, spliced, or resolved: return it, pass it to a slot, or use it as another quotation’s hole. A quotation inside hand-built expression syntax, such as a call’s argument list or a declaration initializer, expands when the compiler resolves that expression.

A local declared Type fills a type position, which lets a quotation declare a variable whose type it computes:

meta static List counter(String name) {
  Type type = %(unsigned);
  return $!{ $type $name = 0; };
}

A Type spells C type keywords such as unsigned and char, and the * of a pointer, as Symbols. It spells every other type name as a String: %("String"), %(* "Point"), %(struct "Tag"). %(String) holds an Atom, so it is an error where it fills a type. The compiler reports type name 'String' must be a String: write %("String").

Holes that name an expression

A $name hole needs a local. When the value is a field, an element, or the result of a call, ${expression} inserts it without one:

#include "x2c.x"
#include "meta.x"

typedef struct Call { List callee; List arguments; Type result; } Call;

meta static List scaled_call(List callee, List a, List b) {
  Call d = {.callee = callee, .arguments = %($a $b), .result = %(int)};
  return $!( ({
    ${d.result} value = ${d.callee}(@{d.arguments});
    value * ${d.arguments.len()};
  }) );
}

macro Expression $sample.scaled(Expr $f, Expr $a, Expr $b) =>
  $scaled_call($f, $a, $b);

static int sum(int a, int b) => a + b;

int main(void) {
  printf("%d\n", $sample.scaled(sum, 2, 5));
  return 0;
}
14

The braces hold ordinary code of the function that contains the quotation. The function evaluates each ${...} once, when it evaluates the quotation, before the quotation builds its code. Holes are evaluated in the order they are written. Names in the braces resolve where the quotation is written. A name that the quotation’s body declares is not visible in the braces, because the body is code for another place. A ${...} hole therefore means the same as a local declared just before the quotation and named with $:

return $!( ${d.callee}(@{d.arguments}) );
// means
List callee = d.callee;
List arguments = d.arguments;
return $!( $callee(@arguments) );

The expression’s declared type gives the hole its kind, as a local’s type does. A Type expression fills a type position, as ${d.result} does above. A String, int, or Symbol expression inserts a literal, so ${d.arguments.len()} inserts 2. A List expression inserts the syntax it holds. @{expression} splices a List, like @name. Each ${...} or @{...} is a separate hole, even when two are spelled alike.

A ${...} belongs to the innermost quotation that contains it. To put one quotation’s code inside another, write the inner quotation as a hole: $!( $inner * ${$!( $a - $one )} ) builds the inner code first and inserts it.

Inside a %(...), %[...], %{...}, or %"..." literal in a quotation’s body, ${...} keeps its literal meaning: it inserts a value when the built code runs. Write ${${expression}} there to insert a value that the function computes. A template Array splices a computed sequence through the same code boundary: %[${@{items}}]. This constructs template slots; ordinary Arrays and Maps do not support runtime splicing. A List’s @{expression} still runs when the generated program constructs that List.

Literal characters need no new staging operator. Write an ordinary string such as "$ @", or %"\$ @" for a percent string. Quoted atom escapes such as %(\$ \@) preserve sigils as data.

${...} works only in quotations. A named template has no function to evaluate it in; it computes with a $meta(...) call or a $(...) slot, which run where it expands.

Code that knows its type

A quotation is bound where it lands, so until then its code has no type. Sometimes the code a function builds must state its type at once: another operation reads the type before the code lands, or the code goes where nothing binds it again. Write the type between $! and the braces that hold the expression:

meta static List doubled(List value) {
  List twice = $!double{ $value * 2 };
  // Code.type(twice) is (double) already.
  return twice;
}

$!T{ expression } builds the expression where it is written and gives it the type T. T is one identifier that names a type, such as int or String. Put any other type in parentheses: a type of several words, as in $!(unsigned long){ ... } or $!(char *){ ... }, or a Type local or ${...} hole whose value is the type, as in $!($result){ $callee(@arguments) }. A kind name such as Unit or Type after $! always names a kind, so a type spelled like one also takes parentheses: $!(Type){ ... }.

A typed quotation states the type the code has. It converts nothing, so write a cast inside the braces when the code needs one.

The rest of the code is built the way a quotation builds it, with two differences:

  • Nothing is bound. Holes keep the syntax their locals hold, a binding becomes a reference to it, and a number, String, or Symbol becomes a literal. A number keeps its exact value and type, and a String is a String literal when T is String. A @items sequence makes each number, String, or Symbol it holds a literal in the same way. A name the expression reads without declaring stays a name and is bound wherever the code is bound, if it is bound at all.
  • The code declares nothing. A typed quotation has no expansion to keep names private to, so a name it needs comes from a hole, such as a local that holds x2c_ident("total"). For the same reason it applies no template; build that code first and insert it. Inside another quotation, write a typed quotation as a hole: ${$!int{ $b }}.

Only the outermost expression receives T. Inner expressions carry no type until something binds them. Write T exactly: the compiler trusts it as it trusts the type a typed call already carries.

A typed reference to a binding the function holds is the shortest form: $!($type){ $binding } is the expression that reads binding as a type.

Types and parameters

A quotation can also build a type or one parameter. $!Type{ ... } holds a type written as a cast writes it. It builds the Type List that a Type local holds:

#include "x2c.x"
#include "meta.x"

typedef struct Point { int x; int y; } Point;

meta static String point_types(void) {
  Type point = $!Type{ Point };
  Type pointer = $!Type{ const $point * };
  Type reader = $!Type{ int (*)($point *) };
  return point.repr() + " " + pointer.repr() + " " + reader.repr();
}

int main(void) {
  printf("%s\n", $point_types());
  return 0;
}
("Point") (* const "Point") (* (func ((* "Point"))) int)

A Type local or a ${...} hole of type Type stands for a type in the braces. The declarator around it builds a new type from it, so $!Type{ const $point * } is a pointer to a constant Point. A type name keeps its spelling: $!Type{ String } is %("String").

$!Param{ ... } holds one parameter declaration. Put the parameters in a function with a sequence hole:

#include "x2c.x"
#include "meta.x"

meta static List sum_function(String name, int count) {
  Array params = [];
  List total = $!( 0.0 );
  for (int i = 0; i < count; i++) {
    List x = x2c_ident(%"x$i");
    params.push($!Param{ double $x });
    total = $!( $total + $x );
  }
  List declared = params.list_free();
  List function = $!Unit{ double $name(@declared) { return $total; } };
  return %($function);
}
macro Unit $sample.define_sum(Literal $name, Literal $count) {
  @sum_function($name, $count)
}
$sample.define_sum("sum3", 3);   // sum3(1.0, 2.0, 3.5) is 6.5

int main(void) {
  printf("%g\n", sum3(1.0, 2.0, 3.5));
  return 0;
}
6.5

Both build their List where they are written, as a typed quotation does. Nothing binds them until the function that holds them is bound. The braces may not declare a name of their own. A parameter takes its name from a hole, so the body reads it through the same x2c_ident(...) local. There is no $!Decl{ ... }, because $!{ ... } and $!Unit{ ... } already build declarations.

What the compiler answers

lib/meta.x declares the compiler operations. An operation on a value is a method of its type: Code for captured code and Type for a semantic type. The rest are x2c_ helpers with no value to act on, such as x2c_ident, x2c_invocation_line and x2c_diagnostic_fail. Code is built with quotations, so the module declares no constructors.

x2c_ident, Code.name, Code.binding_spelling, Type.parts, x2c_diagnostic_fail and x2c_diagnostic_warn work in every meta function. The queries that read the compiler’s symbol table, such as Code.type, Type.fields and Type.resolve, also work in every meta function: the compiler answers a project function’s query while the call waits, in the state of the call’s site. TypeInfo and Source parameters still deliver a description in one argument. The operations are grouped here by the task, not by signature; the module reference lists every declaration, and the language reference gives their semantics.

Building code

A quotation builds the code, and a typed quotation of one value, such as $!int{ $count }, is the literal expression that holds it. x2c_ident checks a name and returns identifier code, which a quotation uses where the code reads the name:

#include "x2c.x"
#include "meta.x"

meta static List call_of(String callee, List argument) {
  List name = x2c_ident(callee);
  return $!( $name($argument) );
}

macro Expression $probe.twice(Expr $value) => $call_of("twice", $value);

static int twice(int n) => n * 2;

int main(void) {
  int n = 21;
  printf("twice %d\n", $probe.twice(n));
  return 0;
}
twice 42

Asking about types and fields

A meta function receives a type as a TypeInfo parameter, described above, or asks the compiler with the queries below. Code.type answers the canonical Type of an expression or binding. Type.fields answers the named fields of a struct or union Type, each as a metadata row whose first element is the field name. Type.layout, Type.resolve and Type.is_value answer the remaining generated-code questions. Type.parts reads only the Type it receives. Type.resolve_member answers which field or method a member access selects. These answers live in the compiler’s symbol table, so a macro body cannot derive them from the code it captured.

Source text and location

A parameter declared Source receives a captured hole together with the text the developer wrote for it: ((text T) (file F) (syntax S)). Code.source_text returns that text, and x2c_embed_text reads the file a captured String literal names beside the source that wrote it and records it as a translation dependency. Both read what the argument carries. x2c_embed_text also accepts an absolute String path. Code.binding_spelling returns the name a binding was declared with. x2c_invocation_file, x2c_invocation_line and x2c_invocation_column give the site of the macro invocation.

Failing with a diagnostic

x2c_diagnostic_fail reports a message at the invocation and stops the expansion. It does not return. Use it when the argument is wrong in a way the macro can see:

#include "x2c.x"
#include "meta.x"

meta static List one_word(Source node) {
  String text = Code.source_text(node);
  if (text.contains(" "))
    x2c_diagnostic_fail("this argument must be one word", %());
  return $!String{ $text };
}

macro Expression $probe.word(Expr $value) => $one_word($value);

int main(void) {
  int seconds = 90;
  printf("word %s\n", $probe.word(seconds));
  return 0;
}
word seconds

The helper receives the complete capture with its source text, which Code.source_text reads. A computed subtree is code data, not a new source capture, and cannot be passed as a Source.

Writing $probe.word(seconds * 2) instead reports the message at that invocation:

sample.x:15:23: macro: this argument must be one word
  printf("word %s\n", $probe.word(seconds * 2));
                      ^

x2c_diagnostic_fail_at reports under a category, such as <macro> or <type>, at a node the macro received, such as one captured statement, instead of at the invocation.

Placing code beyond the result

x2c_enclosing answers the syntax around the invocation: the initialized <declarator>, the block item (<statement>), the <function>, or the <unit>. x2c_place adds code the result cannot hold: %(after-statement) after that declarator or block item, %(block-exit) on every exit from the block after it, as a defer there runs, %(function-entry) at the entry of the enclosing function before its first statement, %(unit-support KEY) among the unit’s file-scope declarations once for each key, and %(unit-init) in the unit’s initialization. Code placed at function entry follows the parameters and keeps the order of its placements. A macro in a lambda body places it in the function that holds the lambda; a $rewrite rule, which runs while the body lowers, places it in the lambda’s own function. A macro in a defer finalizer places it in the function that holds the defer; a $rewrite rule that places it while the finalizer lowers is rejected, because the finalizer runs as its own callback. A failed expansion leaves none of it behind. Placed code that declares a name takes it from x2c_binding_fresh(role), which returns a binding the compiler names, so the result can refer to the same binding. Code placed once under %(unit-support KEY) takes its name from x2c_binding_for(KEY, role), which returns the same binding for the same key in a unit, so every result that refers to it agrees. Here the counter runs after each statement that traces a value:

#include "x2c.x"
#include "meta.x"

static int traced = 0;

meta static List trace_after(List value) {
  x2c_place(%(after-statement), $!{ traced++; });
  return value;
}

macro Expression $trace(Expr $value) => $trace_after($value);

int main(void) {
  printf("%d %d\n", $trace(1), traced);
  printf("%d\n", traced);
  return 0;
}
1 0
1

$auto is written this way: it places a release after the declarator it initializes, and the declaration checks that the expansion is its complete initializer before it binds that release.

Rewriting a function definition

$rewrite from rewrite.x registers a meta function as a rule for the code its macro builds. When that macro is a Unit macro whose body is one function definition, or only its one Function hole, the rule receives each function definition the program writes once, after binding and typing and before the body lowers. A definition that the program’s own meta code places or returns is the program’s. A meta function whose body uses only what the runtime library provides also has a runtime form, an ordinary C function in its unit, and that definition is the program’s, so the rule receives it. A definition that the compiler writes while lowering is not offered: a lambda’s function, a defer’s cleanup, a Func adapter, a protocol’s forwarding member, or the compiler’s own replacement of a definition. The statements such a definition holds from the program still reach the program’s statement rules. The rule returns the definition unchanged to decline, or a replacement definition. The replacement is lowered as written and offered to the other rules, but not again to the rule that returned it. A pattern that spells its return type, such as int $name(...), is tried only on definitions with that return type and storage, before the rules whose pattern holds a hole there:

#include "x2c.x"
#include "rewrite.x"

static int entries = 0;

macro Unit $any_function(Function $function) { $function }

$rewrite($any_function)
meta Code count_entries(Code function) {
  if (!Code.name(function).startswith("counted_")) return function;
  match (function) case %(function ?type ?declarator ?):
    return %(function $type $declarator
      (block ${$!{ entries++; }} @{Code.body(function)}));
  return function;
}

int counted_next(int x) { return x + 1; }

int main(void) {
  counted_next(1);
  counted_next(2);
  printf("%d\n", entries);
  return 0;
}
2

The compiler binds each of these under its x2c name and derives the Lisp name from it: a method keeps its spelling, so Code.binding_spelling is Code.binding_spelling in Lisp, and in a helper each _ becomes ., so x2c_invocation_line is x2c.invocation.line. A Lisp form has no quotation, so the Lisp library also defines x2c.literal.string, x2c.literal.int and x2c.literal.symbol, which build the literal a $(...) form returns for a value.

The compiler’s shipped components lower language features with the same $rewrite decorator. A program definition spelled like a shipped component’s meta function or helper is a separate definition: shipped rules and templates resolve their own names to the copies the compiler links.

Functions that need the compiler

Compiler queries exist only inside a compiler. A meta function that calls one, directly or through another meta function, therefore has no valid runtime form, and the compiler emits no definition for it. A body containing a source-template constructor is also compile-time-only, as are its meta callers. A call to one from a runtime body is diagnosed where it is written. Calling one_word from an earlier section at run time gives:

sample.x:19:22: macro: 'one_word' can only be called at compile time
    List n = one_word(node);
                     ^
  note: reason: it reaches a compiler operation, so no unit emits a
  definition for it; call it from a macro or another meta function

In the complete shape example below, shape_names and shape_reads construct source code and have no runtime forms. The consumer uses their returned code.

A meta function that needs no compiler query, like poly above, keeps both forms and is emitted normally.

A complete example

Two ordinary source files. shape.x holds the meta functions and the macros that call them. shape_fields reads the fields from the TypeInfo the compiler sends. shape_names and shape_reads turn them into code.

#include "meta.x"

/* The named fields of a struct-typed expression, in declaration order. */
meta static List shape_fields(TypeInfo type) => type.assoc(<fields>);

/* One `String` literal holding those field names, comma separated. */
meta List shape_names(TypeInfo type) {
  Array names = [];
  foreach (List field, shape_fields(type)) names.push(field.car());
  return $!String{ ${String.join(", ", names)} };
}

/* `{ p.x, p.y, p.z }`, built from the fields rather than written out. */
meta List shape_reads(List receiver, TypeInfo type) {
  Array reads = [];
  foreach (List field, shape_fields(type)) {
    String member = field.car();
    reads.push($!( $receiver.$member ));
  }
  List items = reads.list_free();
  return $!( { @items } );
}

macro Expression $shape.names(Expr $value) => $shape_names($value);

macro Expression $shape.reads(Expr $value) => $shape_reads($value, $value);

The second file includes shape.x and uses its public macros. The include also makes its nonstatic meta functions available.

#include "x2c.x"
#include "meta.x"

#include "shape.x"

typedef struct Point { int x, y, z; } Point;

int main(void) {
  Point p = { 2, 3, 4 };
  int reads[3] = $shape.reads(p);
  printf("names %s\n", $shape.names(p));
  printf("reads %d %d %d\n", reads[0], reads[1], reads[2]);
  return 0;
}
names x, y, z
reads 2 3 4

The field names never appear in the program. The compiler supplied them, and the meta functions built "x, y, z" and { p.x, p.y, p.z } from them.