1# statement
2
3## Rules
4
5  * *object-definition*
6  * LABEL **:** *object-definition*
7  * LABEL **:** *place*
8  * *direction*
9  * VARIABLE *assignment-op* *expr*
10  * **define** VARIABLE CODEBLOCK
11  * **print** *print-argument* (**,** *print-argument*)\*
12  * **assert (** *expr* **==** *expr* **)**
13  * **assert (** *position* **==** *position* **)**
14
15
16## Labels
17
18A label can be attached to either an *object* or a *place* so that
19the object or place can be more easily referenced by subsequent statements.
20Labels always begin with an upper-case ASCII character.
21
22Labels do not have to be unique.  When there are two or more
23labels with the same name, the later one takes precedence.
24This allows a label to be effectively redefined.  New labels do not
25come into existence until after the object or place to which they are
26attached has been completely parsed and analyzed.  This allows labels
27to be redefined in terms of themselves.  Consider an example:
28
29~~~~~
30/* 01 */        down
31/* 02 */  Root: dot "First \"Root\"" above color red
32/* 03 */        circle wid 50% at Root + (1.5cm, -1.5cm)
33/* 04 */        arrow dashed from previous to Root chop
34/* 05 */  Root: 3cm right of Root   // Move the location of Root 3cm right
35/* 06 */        arrow from last circle to Root chop
36/* 07 */        dot "Second \"Root\"" above color blue at Root
37~~~~~
38
39Line 05 redefines Root in terms of itself.
40In the rendering below, you can see that the dashed arrow drawn before
41Root was redefined goes to the original Root, but the solid arrow drawn
42afterwards goes to the revised location for Root.
43
44~~~~~ pikchr center toggle
45/* 01 */        down
46/* 02 */  Root: dot "First \"Root\"" above color red
47/* 03 */        circle wid 50% at Root + (1.5cm, -1.5cm)
48/* 04 */        arrow dashed from previous to Root chop
49/* 05 */  Root: 3cm right of Root   // Move the location of Root 3cm right
50/* 06 */        arrow from last circle to Root chop
51/* 07 */        dot "Second \"Root\"" above color blue at Root
52~~~~~
53
54## Variables
55
56Variable names begin with a lower-case ASCII letter or with "`$`"
57or with "`@`".  The $- and @- variable names are a Pikchr extension
58designed to help prevent collisions between variable names and the
59(numerous) keywords in the Pikchr language.
60
61Pikchr has built-in variables as follows:
62
63>
64| Variable Name |    Initial Value    |: Purpose         |
65------------------------------------------------------------------------------
66| arcrad        |: 0.250 :| Default arc radius                               |
67| arrowhead     |: 2.000 :| *Not used by Pikchr*                             |
68| arrowht       |: 0.080 :| Length of arrowheads                             |
69| arrowwid      |: 0.060 :| Width of arrowheads                              |
70| boxht         |: 0.500 :| Default height of "box" objects                  |
71| boxrad        |: 0.000 :| Default corner radius for "box" objects          |
72| boxwid        |: 0.750 :| Default width for "box" objects                  |
73| charht        |: 0.140 :| Average height of a character                    |
74| charwid       |: 0.080 :| Average width of a character                     |
75| circlerad     |: 0.250 :| Default radius for "circle" objects              |
76| color         |: 0.000 :| Default foreground color                         |
77| cylht         |: 0.500 :| Default height for "cylinder" objects            |
78| cylrad        |: 0.075 :| Default minor axis for ellipses in a cylinder    |
79| cylwid        |: 0.750 :| Default width of a "cylinder" object             |
80| dashwid       |: 0.050 :| Default width of dashes in dashed lines          |
81| dotrad        |: 0.015 :| Default radius for a "dot" object                |
82| ellipseht     |: 0.500 :| Default height for "ellipse" objects             |
83| ellipsewid    |: 0.750 :| Default width for "ellipse" objects              |
84| fileht        |: 0.750 :| Default height for "file" objects                |
85| filerad       |: 0.150 :| Default corner fold length for "file" objects    |
86| filewid       |: 0.500 :| Default width for "file" objects                 |
87| fill          |: -1.00 :| Default fill color.  Negative means "none"       |
88| lineht        |: 0.500 :| Default length for lines drawn up or down        |
89| linewid       |: 0.500 :| Default length for lines drawn left or right     |
90| movewid       |: 0.500 :| Default distance traversed by a "move"           |
91| ovalht        |: 0.500 :| Default height of an "oval" object               |
92| ovalwid       |: 1.000 :| Default width of an "oval" object                |
93| scale         |: 1.000 :| Scale factor for drawing.  Larger is bigger.     |
94| textht        |: 0.500 :| *Not used by Pikchr*                             |
95| textwid       |: 0.750 :| *Not used by Pikchr*                             |
96| thickness     |: 0.015 :| Default line thickness for all objects           |
97
98In addition to the above, Pikchr recognizes the following variables
99which are not initially defined, but if they are defined by the script
100have special properties:
101
102>
103| Variable Name     |: Purpose                           |
104------------------------------------------------------------------------------
105| bottommargin  | Extra border space added to the bottom of the diagram      |
106| fgcolor       | Use this foreground color in place of black                |
107| fontscale     | Scale factor applied to the font size of text              |
108| layer         | The default layer for all subsequent objects               |
109| leftmargin    | Extra border space added to the left of the diagram        |
110| margin        | Extra border space added to all four sides of the diagram  |
111| rightmargin   | Extra border space added to the right side of the diagram  |
112| topmargin     | Extra border space added to top top side of the diagram    |
113
114
115The "VARIABLE *assignment-op* *expr*" syntax is able to modify the value
116of built-in variables, or create new variables.  In legacy-PIC, the only
117*assignment-op* was "`=`".  Pikchr adds "`+=`", "`-=`", "`*=`", and
118"`/=`" to make it easier to scale existing variables up or down.
119
120### Conflicts between variable names and keywords
121
122Some of the built-in variables have names that conflict with keywords:
123
124  *  color
125  *  fill
126  *  thickness
127
128To access such variables as part of an expression, simply put them inside
129of parentheses.  For example, to set the thickness of a box to be twice
130the default thinkness:
131
132~~~ pikchr center toggle source
133   box "Normal"
134   move
135   box "Double" "Thick" thickness 2*(thickness)
136~~~
137
138## Define
139
140The "`define`" statement creates a [macro](./macro.md)
141that can then be called in subsequent text.
142
143## Print
144
145The "`print`" statement prints the strings and the values of the expressions
146in its argument into the generated output in front of the
147"`<svg>`" element for the diagram.  This facility is intended for testing
148and debugging purposes.  There is no known practical use for "`print`" in
149a production Pikchr script.
150
151The following Pikchr script demonstrates the effect of "print".
152Click to toggle between the script and its rendering.
153
154~~~ pikchr toggle source indent
155   oval "Hello, World!" fit
156   print "Oval at: ",previous.x, ",", previous.y
157   line
158   oval "2nd oval" fit
159   print "2nd oval at: ",previous.x, ",", previous.y
160~~~
161
162## Assert
163
164The "`assert`" statement is intended for testing and debugging of Pikchr
165scripts.  An assert() is a no-op if the equality comparison in its
166argument is true.  But it raises an error if the condition is false.
167
168Consider this script:
169
170~~~
171   oval "Hello, World!" fit
172   assert( last oval.w == last oval.e ); # <-- should fail
173~~~
174
175And its rendering:
176
177~~~ pikchr
178   oval "Hello, World!" fit
179   assert( last oval.w == last oval.e ); # <-- should fail
180~~~
181