THIS HAS BEEN IMPLEMENTED|
The syntax for referencing parameters in g-code is awkward and difficult to use because the user must remember the number associated with each parameter. This page contains a proposal (by lerman) for the syntax and semantics of a named parameter feature. This syntax was ultimately discarded in favor of the Named Parameters syntax. The description here has been left for historical purposes.|
After a discussion on IRC (December 30, 2006) about how nasty the proposed named parameter syntax looks (Named Parameters), here is an alternative.|
#<named parameter here>references a named parameter. The <> characters provide for neat bracketing that is relatively unobtrusive compared to using
#named parameter here$with a $ terminator. These parameters would be local to the scope in which they were assigned.
"#[abcdef]" is a reference to a parameter named abcdef. So: "#[abcdef] = 1.2" would assign the value 1.2 to a parameter named abcdef. "#[feedrate] = #[abcdef]" would assign the value of the parameter named abcdef to the parameter named feedrate. It is important to note that following the convention for g-code lines, whitespace characters are removed from parameter names and characters are translated to lower case internally. So, "feed Rate" is the same as "feed rate" or "feedrate". Also, at least in the initial implementation, the scanning of a parameter name will start at the "[" character after the "#" and continue until the first "]" character. Including comments within parameter names will probably NOT do what is desired.|
The scope of a parameter name is limited to the main program or the subprogram in which it is defined. Thus, subroutines defined by different users may use the same variable names without clashes. Named parameters may NOT be used to pass variables among subroutines. Named parameters are NOT defined or stored in var files.
This proposed change will NOT break any existing EMC targeted g-code.
#<_global named parameter here>.Named parameters beginning with '_' are global. They are accessible from within called subroutines and may set values within subroutines that are accessible to the caller. As far as scope is concerned, they act just like regular numeric parameters. They are not stored in files.
Note: a choice was made to have the default define *local* parameters while the '_' case defines global parameters. The reason for this is that local parameters are probably more common.|
Note: the global parameters _a, _b, _c, ... _z have been reserved for special use. In the future, they will provide access to the last Aword, Bword, Cword, etc. This will be used as part of an implementation of User Defined Gcodes.|
1) I suggest that somehow one needs to be able to alias named parameters to numeric ones (and to each other), for example, so one could use "#[xWkOff?]" instead of "#". This need not be in the g-code (indeed would better not be) but needs to be "integrator" definable so one could have "#[fixOffstX?]" or a French system might have|
"#[xDecPiece?]". This suggestion, or course, causes difficult1es with the scope semantics.
- sorry about the brackets being links - cannot see how to avoid this :=(
Note: all parameter names are converted to lower case and have whitespace removed. This is an unfortunate consequence of the rs274ngc standard.|
Please add your comments here.
I think I have found an existing program this change will break:
G0 X #[SQRT]
maybe you can fix this by using a new character that's currently a syntax error:
G0 X #[SQRT] (old behavior)
G0 X #_SQRT_ (new behavior)
Actually, a separate delimiter may not be needed (though it would simplify the code). Since a named variable must be the only thing within a set of brackets, any text token that isn't followed by a ']' must be a function (or an error).
#[feed rate] = 1 ; feed rate is followed by a ], so it's a variable name
#[Sqrt] ; sqrt is followed by a [, so it's not a variable. this ends up being #3
#[abs[feed rate]] ; could be an error (no # before feed rate brackets), or could be allowed since it's already inside an expression
(Note: named owords have not been implemented yet)|
Named owords can have a similar syntax.|
After the above comments, lerman says:|
At this point, I'm considering use a "$" character as a string terminator.
So, this would be written "X#abc$ Y2".
There seems to be some demand for global named parameters. One approach I'm thinking of is as follows:
Variable names that are specified with a leading "$" would be local
variables. Variables without the leading "$" would be global variables.
#abc$ would refer to a global variable
#$abc$ would refer to a local variable
Initially, neither local nor global variables would be saved in var files.
In the longer run, we might make the changes necessary to save global
The scope of local variables would be limited to the invocation of the main
or subroutine it was enclosed in. Subroutines called at deeper levels have
access only to those at their level.
o<a label> is a named label. Named labels are of local scope with the exception of the named labels which refer to subroutines. Thus, two subroutines may have owords "o<Loop>" without causing an error.|
BTW: My plan (or intention -- plan might be too strong a word) is to also|
implement named o-words.
Then Ofoobargag$ would be a named o-word. In that case, foobargag would be a
globally accessible o-word. O$foobargag would be an o-word of local scope.
It would be visible only within the subroutine (or main program) in which it
was defined. That would avoid name clashes caused by subroutines written by
multiple persons using the same names (or numbers).
Example (with both sets of changes):
(Program to mill a helical cam)
#$CenterX?$ = #1 #$CenterY?$ = #2
#$ToolDia?$ = #3
#$MinRadius?$ = #4
#$MaxRadius?$ = #5
#$NumberOfSteps?$ = #6
#$FeedRate?$ = #7
#$Depth$ = #8
#$tool radius$ = [#$ToolDia?$/2.0]
#$current step number$ = 0
#$at depth$ = 0
o$CountSteps?$ while [#$current step number$ LT #$NumberOfSteps?$]
#$current angle$ = [#$current step number$ * 360. / #$NumberOfSteps?$]
#$radius at current angle$ = [#$MaxRadius?$ - [#$current angle$/360] * [#$MaxRadius?$ - #$MinRadius?$] + #$tool radius$]
#$X$ = [[0 - #$radius at current angle$ * cos[#$current angle$]] + #$CenterY?$]
#$Y$ = [[#$radius at current angle$ * sin[#$current angle$]] + #$CenterX?$]
o$TestDepth?$ if [#$at depth$ NE 1]
#$at depth$ = 1
G1 F#$FeedRate?$ X#$X$ Y#$Y$ (Go to point)
G1 F[#$FeedRate?$/5.0] Z#$Depth$ (Plunge to depth)
G1 F#$FeedRate?$ X#$X$ Y#$Y$ (Mill to point)
#$current step number$ = [#$current step number$ + 1]
G0 Z.2 (Retract)
([0,0,0] is at surface in center of cam)
(Start above surface with clear path to initial point)
(To do multiple passes, lie about the tool diameter first pass)
oMillCam?$ call [.800][.5][1.0][5.0][-2.220]
oMillCam?$ call [.650][.5][1.0][5.0][-2.220]
oMillCam?$ call [.530][.5][1.0][5.0][-2.220]
oMillCam?$ call [.500][.5][1.0][5.0][-2.220]
All refer to the same subroutine.
Local named owords are stored internally as the subroutine name, followed by an '_', followed by the local oword name. In the case of a local named oword that is not within a subroutine, the letters 'main_' are prepended to the name. The character '_' may be part of an o_word name, but may NOT be the first character.
Also implemented new comment features
Comments from IRC|
SWPadnos> you need to be able to tell whether the operation is a write to the variable or a read from it. a write would create the variable, a read of a nonexistent variable would be an error (or warning)