# 10. cschem - forge

{des10:0} The purpose of the forge plugin is to provide an easy to implement yet generic way for describing attribute transformations in attributes (e.g. in a library symbol) during compilation.

## 10.1. Unconditinal forge

{des10:1} The forge plugin works from the array attribute forge, which is taken as an ordered list of atomic steps to execute on attributes. For portability of data, the forge plugin needs to implement exactly the operations described below.

{des10:2} Each entry of the array is one operation. An operation is split into tokens separated by the separator character, which is a non-alphanumeric character following the operator (first token). For example sub,^dip,DIP,footprint is a valid operation that uses regexp to replace leading "dip" to DIP in the footprint attribute. Since sub is followed by a comma, the token separator is comma.

{des10:3} Operations work with the current values of attributes at the time of plugin execution during compilation of the abstract model. If destination attribute doesn't exist, it is created.

{des10:4} If referenced source attribute of an operation does not exist, the operation is silently skipped.

{des10:5} Operation summary
operations and arguments | in-place | array? | short description
--- | --- | --- | ---
sub,pat,str,attr | yes | map | substitutes one match of regex pattern pat with str in attr
gsub,pat,str,attr | yes | map | substitutes all matches of regex pattern pat with str in attr
suba,pat,ref,attr | yes | map | substitutes one match of regex pattern pat with the value of the ref attribute in attr
gsuba,pat,ref,attr | yes | map | substitutes all matches of regex pattern pat with the value of the ref attribute in attr
delete,attr | yes | atomic | deletes (removes) the attribute
scalar,attr | yes* | atomic | create attr as scalar if it does not exist; throw an error if it exists as an array
array,attr | yes* | atomic | create attr as array if it does not exist; throw an error if it exists as a scalar
copy,dstattr,srcattr | no | atomic | copies the value of srcattr to the destination attribute dstattr (overwriting or creating it)
append,dstattr,srcattr | no | darr | appends the value of the source attribute srcattr to the value of the destination attribute dstattr
prepend,dstattr,srcattr | no | darr | prepends the value of the source attribute srcattr to the value of the destination attribute dstattr

{des10:6} In-place operations modify existing attributes in place. They are no-op for non-existing attributes.

{des10:7} If addressed attribute of the operation is an array, the operation will behave according to the "array?" column:

- map: on copy, an array is mapped into an array; on edit-in-place each array element is edited individually
- atomic: if array, the whole array is dealt with at once, as an atomic object; if scalar, result is a scalar too
- darr: if destination is an array, the source (or each element of the source, if it's an array) is combined into the destination array. Fails if source is array and destination is scalar.

## 10.1. Conditinal forge

{des10:8} Attributes whose key start with forge-if/ are used for conditional execution of forge. The remainder of the attribute key is an arbitrary identifier, for example forge-if/dnp is commonly used for setting a DNP (do-not-populate) attribute depending on the current view and/or stances.

{des10:9} The attribute is an array; the first entry contains the condition; the rest of the entries contain the same forge operations as the unconditional forge attribute. However, the operations are performed only if the expression in the first entry evaluates to true.

{des10:10} The condition is an expression in the usual infix form. There are three data types supported:

- integer: a sequence of digits (decimal number, not larger than 2^31-1)
- string literal: a sequence of characters enclosed in double quotes; a double quote can be added using the usual \" form, and \\ is taken as a single backslash
- constant: an id or id.id that is going to be substituted with the value of the named constant; the value is always a string

{des10:11} The following binary operators are defined for strings (where each oparand is a string literal or a constant):

- str == str is 1 if the two strings match (case sensitive), 0 otherwise; the result is an integer
- str != str is 0 if the two strings match (case sensitive), 1 otherwise; the result is an integer

{des10:12} The following binary operators are defined for integers, with their usual meaning and precedence:

- == means equal
- != means not-equal
- <
- >
- <=
- >=
- && means logic "and"
- || means logic "or"
- -, +, *, / are the usual subtract, add, multiply, divide
- % is the remainder of an integer division

{des10:13} The following non-binary operators are defined for integers, with their usual meaning and precedence:

- ! is the unary "not" operator
- - is the unary minus

{des10:14} Parenthesis affects the precedence the usual way.

## 10.2. Stances for conditinal forge

{des10:15} One of the factors that can be used in conditional forge is project stance, which is a collection of project build options: when the same project can be used to produce differently configured boards/circuits, stance values determine which option is currently displayed or exported.

{des10:16} Each stance has a name and an arbitrary textual value. Optionally the implementation may provide a list of possible values. All values are invented by the user.

{des10:17} The implementation is free to define stance names but the following three must be supported:

standard stances
name | usage provisions
--- | ---
model | for the simplest cases, this single stance selects which one of the build configurations is used (e.g. which model or variant of the board is made)
sub_major | major subtype; if there's a build option that is orthogonal to the model, this stance should be used
sub_minor | minor subtype; if there's a build option that is orthogonal to both the model and the sub_major stances, this stance should be used

## 10.3. Standard id.id substitution

{des10:18} The implementation must support at least the following id.id substitutions:

- view.name is the name of the current view
- stance.model is the current value of the project stance called model
- stance.sub_major is the current value of the project stance called sub_major
- stance.sub_minor is the current value of the project stance called sub_minor