Gcode++
31 Mar 2022 22:42 #238957
by jeffel
Gcode++ is an upgrade for Gcode. There is really a great deal that can be done with gcode but very few pursue writing it because it is such a PITA to write! I get it!
I decided to fix this by writing a compiler that can take "cleaned up" gcode (gcode++) and convert it to regular gcode for the primitive interpreter. I now very much enjoy writing gcode, using this tool. You can find everything on my website at:
WilliamsLabs.net
PS - I have been using this and tweeking it for quite some time now. I thought it would be a shame if no one else got any benefit from this labor except myself, so thought I would try posting here to see if the community might be interested. This is NOT about money or anything like that, because:
True engineers only like to do two things i.e Share ideas & Play with the toys
They are children at play.
I decided to fix this by writing a compiler that can take "cleaned up" gcode (gcode++) and convert it to regular gcode for the primitive interpreter. I now very much enjoy writing gcode, using this tool. You can find everything on my website at:
WilliamsLabs.net
PS - I have been using this and tweeking it for quite some time now. I thought it would be a shame if no one else got any benefit from this labor except myself, so thought I would try posting here to see if the community might be interested. This is NOT about money or anything like that, because:
True engineers only like to do two things i.e Share ideas & Play with the toys
They are children at play.
Please Log in or Create an account to join the conversation.
01 Apr 2022 16:41 #239003
by jeffel
This is a long answer to question that may not have been asked, so I am shooting from the hip,
but just to have what I am doing properly understood, consider the following:
The most efficient input stream for a digital processor is one that can be immediately executed without interpretation... For a CPU, this is known as machine code. It is possible to hand code such programming (something I have actually done), but it is tedious and error prone. At the next programming level, we assign mnemonics, human readable alpha-numeric symbols, to represent machine code instructions. This type of code generator is called an assembler. You can do a lot with an assembler, but it is still very primitive (as a language). However, it represents the native language, if you will, of the machine. This means it is the fastest and most efficient form of coding for the processor. Something you really want when speed is important. Now let me compare this to a CNC instruction processor. CNC gcode is not really at the assembler level but it is analogous at the CNC machine control level. In gcode, a level of interpretation has been added to the point where it is possible to human encode the stream. I say possible, but for most part, still unpleasant, but human readable. Still, this is a good scenario. The interpreter does as little interpreting as possible, which promotes speed and efficiency. The stream that enters a gcode interpreter has been human tokenized. For instance, when the coding #<xyz> comes in, it is immediately known to be a variable. If the interpreter had to figure out, from the language construct, that xyz is a variable, if we take out the cryptic elements that tell the CNC interpreter exactly what each item on the code line is, we begin the process of bogging down the system with things that don’t need to be there. Compared to compiled code, interpreters that try to do this are notoriously slow. For CNC gcode, at this point, I think we have a nice trade off between execution and readability, but not write-ability, at least for humans The job of a compiler is to manipulate lower level code to effect higher level language constructs. A single compiler line may sometimes generate several lines of machine level instructions for just one higher level command, and my case is no different. With the gcode++ compiler, I also implement Macros, Arrays, a PushPop stack, and a free flowing language text (no forced line orientation). This would be very complex to implement in an interpreter even if desireable.
No, this is a job for a compiler.
but just to have what I am doing properly understood, consider the following:
The most efficient input stream for a digital processor is one that can be immediately executed without interpretation... For a CPU, this is known as machine code. It is possible to hand code such programming (something I have actually done), but it is tedious and error prone. At the next programming level, we assign mnemonics, human readable alpha-numeric symbols, to represent machine code instructions. This type of code generator is called an assembler. You can do a lot with an assembler, but it is still very primitive (as a language). However, it represents the native language, if you will, of the machine. This means it is the fastest and most efficient form of coding for the processor. Something you really want when speed is important. Now let me compare this to a CNC instruction processor. CNC gcode is not really at the assembler level but it is analogous at the CNC machine control level. In gcode, a level of interpretation has been added to the point where it is possible to human encode the stream. I say possible, but for most part, still unpleasant, but human readable. Still, this is a good scenario. The interpreter does as little interpreting as possible, which promotes speed and efficiency. The stream that enters a gcode interpreter has been human tokenized. For instance, when the coding #<xyz> comes in, it is immediately known to be a variable. If the interpreter had to figure out, from the language construct, that xyz is a variable, if we take out the cryptic elements that tell the CNC interpreter exactly what each item on the code line is, we begin the process of bogging down the system with things that don’t need to be there. Compared to compiled code, interpreters that try to do this are notoriously slow. For CNC gcode, at this point, I think we have a nice trade off between execution and readability, but not write-ability, at least for humans The job of a compiler is to manipulate lower level code to effect higher level language constructs. A single compiler line may sometimes generate several lines of machine level instructions for just one higher level command, and my case is no different. With the gcode++ compiler, I also implement Macros, Arrays, a PushPop stack, and a free flowing language text (no forced line orientation). This would be very complex to implement in an interpreter even if desireable.
No, this is a job for a compiler.
The following user(s) said Thank You: Grotius
Please Log in or Create an account to join the conversation.
01 Apr 2022 19:29 #239012
by Grotius
Hi Jeffel,
Interesting. I currently work also with assembler in Ghidra. It shows the decompiler output of assembler in c++ language.
It's very interesting too see how things are done in assembler language. And it gives you more idea's how to write your own
programming language.
Interesting. I currently work also with assembler in Ghidra. It shows the decompiler output of assembler in c++ language.
It's very interesting too see how things are done in assembler language. And it gives you more idea's how to write your own
programming language.
Please Log in or Create an account to join the conversation.
01 Apr 2022 20:46 #239015
by rodw
I'm well aware of the differences between machine code, assembler code and higher level languages. Another language which is designed to be created and consumed by machines that is human readable is postscript. Postscript files are consumed by an interpeter embedded into the output device. Gcode is human readable code that is interpreted by the machine controller and converted to precise coordinated motion instead of precise bitmapped patterns. To say gcode is machine code is quite a stretch. I do agree that both languages are unpleasant but postscript is far less pleasant to gcode for a human. They are both operating in the cartesian coordinate space.
The linuxcnc gcode interpreter takes an input file and tokenises it into a buffer containing tokens that are low level machine instructions, your "real" machine code.. Note that:
The Linux interpreter designed so it could be replaced with another language but nobody has ever bothered to do this.
The linuxcnc interpreter knows how to tokenise gcode into true machine code to achieve motion
The real opportunity for gcode++ would be to embed your "compiler" so that when a gcode++ file was opened by linuxcnc, it was immediately converted to tokenised gcode commands using the linuxcnc interpreter model. Doing it this way, gcode is never actually created and you end up with a true compiler. The user never sees any gcode. To me, most of the architecture required to achieve this full integration already exists.
The other messier alternative would be to write a linuxcnc filter program that takes a gcode++ input file when opened in Linuxcnc and pipes it through your compiler and opens the output. The user would see the resulting gcode file as the file that is loaded. Very simple but not nice for the user.
The linuxcnc gcode interpreter takes an input file and tokenises it into a buffer containing tokens that are low level machine instructions, your "real" machine code.. Note that:
The Linux interpreter designed so it could be replaced with another language but nobody has ever bothered to do this.
The linuxcnc interpreter knows how to tokenise gcode into true machine code to achieve motion
The real opportunity for gcode++ would be to embed your "compiler" so that when a gcode++ file was opened by linuxcnc, it was immediately converted to tokenised gcode commands using the linuxcnc interpreter model. Doing it this way, gcode is never actually created and you end up with a true compiler. The user never sees any gcode. To me, most of the architecture required to achieve this full integration already exists.
The other messier alternative would be to write a linuxcnc filter program that takes a gcode++ input file when opened in Linuxcnc and pipes it through your compiler and opens the output. The user would see the resulting gcode file as the file that is loaded. Very simple but not nice for the user.
Please Log in or Create an account to join the conversation.
01 Apr 2022 21:06 #239017
by jeffel
Grotius, happy to make your acquaintance,
Yes indeed, Assembler today is little appreciated. I remember, back in the days when mini-computers were the rage, I wrote a lot of IBM 370 assembler for a construction company. The main problem was that the resident staff were trying to write things in Basic or Fortran, etc. that were difficult or impossible to do in those higher level languages, but NO problem to implement in Assembler, because with assembler you can do anything the processor is capable of. In one case, about 30 pages of BASIC were reduced to a single page of Assembler coding (who would of thought that today?), and it was blazingly fast.
In a similar way, a good gcode subroutine can replace 1000's of lines of CAM, and is repeatable by adjusting the input parameters. In this case, It becomes a powerful command in your toolbox, but very few people seem to think this way today.
Yes indeed, Assembler today is little appreciated. I remember, back in the days when mini-computers were the rage, I wrote a lot of IBM 370 assembler for a construction company. The main problem was that the resident staff were trying to write things in Basic or Fortran, etc. that were difficult or impossible to do in those higher level languages, but NO problem to implement in Assembler, because with assembler you can do anything the processor is capable of. In one case, about 30 pages of BASIC were reduced to a single page of Assembler coding (who would of thought that today?), and it was blazingly fast.
In a similar way, a good gcode subroutine can replace 1000's of lines of CAM, and is repeatable by adjusting the input parameters. In this case, It becomes a powerful command in your toolbox, but very few people seem to think this way today.
Please Log in or Create an account to join the conversation.
01 Apr 2022 22:08 - 01 Apr 2022 22:21 #239030
by Grotius
Hi Jeffel,
because with assembler you can do anything the processor is capable of.
I was wondering. When you write a new programming language. You could parse it to assembler language with a script.
Then creating a new programming language is actually simpler then i thought.
Or am i thinking too simple here?
If you use a rich text for progamming language. Then you could write with word a program.
Then code comments could include graphics, pictures, etc. At this moment in qt you can not do that.
This seems not to be valid code for c++.
for(int i=0; i<10; i++( int j=0; j<10; j++ ( int k=0; k<10; k++ ))){ }
because with assembler you can do anything the processor is capable of.
I was wondering. When you write a new programming language. You could parse it to assembler language with a script.
Then creating a new programming language is actually simpler then i thought.
Or am i thinking too simple here?
If you use a rich text for progamming language. Then you could write with word a program.
Then code comments could include graphics, pictures, etc. At this moment in qt you can not do that.
This seems not to be valid code for c++.
for(int i=0; i<10; i++( int j=0; j<10; j++ ( int k=0; k<10; k++ ))){ }
Last edit: 01 Apr 2022 22:21 by Grotius.
Please Log in or Create an account to join the conversation.
01 Apr 2022 22:43 #239034
by jeffel
Wow, this is getting interesting..
Hi Rodw, Nice to meet you.
First let us clear the air, shall we?
1) although I responded to your message, it was not written to you personally. I just wanted to clarify my position to other possible readers on just what this tool does. I was not trying to tutor you.
2) I did not say that gcode is machine code, far from it. I was simply saying the obvious, that it is analogous, that is, in many cases it is the de facto standard low level interface for machine control, so if I convert to it, I can control the machine, and get it to do just about anything the machine is capable of.
While I appreciate the idea that a better interpreter would be nice for linuxcnc (and would like to see it), I don't see that is necessary to get the benefit of a compiler. I am already bypassing the problem. When I type "make" on a ++ file, my computer compiles the file into an .ngc and ships it to my machine. Most of the time I never see or need to see the .ngc file. However, once in while, I do, to figure out what the interpreter is complaining about.
You seem to be very knowledgeable. I think we are going to get along just fine. When I started into electronics in the 50's, the vacuum tube was state of the art. I don't consider myself any smarter than anyone else, but hey, this isn't my first rodeo.
My purpose in posting my tool was to share it. It would be deeply gratifying to me if someone wrote back and said something like "gee, we tried your tool and writing gcode is soooo much easier now". That would make my day. On the other hand, if it is of no value to anyone else, it has been of great value to me, both to develop it, and use it. I probably would not have done anything much with gcode if I had to write it "as it is". So I figured there might be a few people out there that would feel the same way, and benefit.
Hi Rodw, Nice to meet you.
First let us clear the air, shall we?
1) although I responded to your message, it was not written to you personally. I just wanted to clarify my position to other possible readers on just what this tool does. I was not trying to tutor you.
2) I did not say that gcode is machine code, far from it. I was simply saying the obvious, that it is analogous, that is, in many cases it is the de facto standard low level interface for machine control, so if I convert to it, I can control the machine, and get it to do just about anything the machine is capable of.
While I appreciate the idea that a better interpreter would be nice for linuxcnc (and would like to see it), I don't see that is necessary to get the benefit of a compiler. I am already bypassing the problem. When I type "make" on a ++ file, my computer compiles the file into an .ngc and ships it to my machine. Most of the time I never see or need to see the .ngc file. However, once in while, I do, to figure out what the interpreter is complaining about.
You seem to be very knowledgeable. I think we are going to get along just fine. When I started into electronics in the 50's, the vacuum tube was state of the art. I don't consider myself any smarter than anyone else, but hey, this isn't my first rodeo.
My purpose in posting my tool was to share it. It would be deeply gratifying to me if someone wrote back and said something like "gee, we tried your tool and writing gcode is soooo much easier now". That would make my day. On the other hand, if it is of no value to anyone else, it has been of great value to me, both to develop it, and use it. I probably would not have done anything much with gcode if I had to write it "as it is". So I figured there might be a few people out there that would feel the same way, and benefit.
Please Log in or Create an account to join the conversation.
02 Apr 2022 01:39 #239038
by jeffel
Hi again Grotius,
Since you have asked, I will try to answer.
The short answer, yes, you are way oversimplifying. The meaning of "parse" and of "compile" are important to understand. Firstly, let me refer you to my document gcode++.pdf on my website. In there I discuss some of the development issues and what constitutes a compiler. Ok, that said,
To parse is to separate into meaningful groupings. In the case of a normal sentence, you could parse out the words using white space to separate them. But that is very simple. If you preparing the text for a compiler, parsing also implies that you recognize what it is that you parsed. You would have to say that this is a "noun", this one is a "verb", etc. so that the compiler, which is going to verify an acceptable syntax, can act on it.
Let's say you had this gcode:
x = 2
s = 4
G01Xx*2+4Ys/3+2
How do you tell, on line 3, what the G code is, which are parameters?, which are numbers, which are the variables?
You get the idea. The parser follows a set of rules to determine the breakout and what each thing is (token). These rules are usually implemented as regular expressions "regex". I have 2 or 3 books on this topic alone.
The compiler receives the stream from the parser and Identifies valid sentences, in the language itself, using the tokens, to translate to the output. But wait? what if the sentence contains other sentences? Suppose you hit an "if" statement. You cannot process that until you know all the statements inside the "if", which may contain other "if" statements, and other blocks of statements, and on and to infinity. You can see, at this point, a recursive nightmare is developing. A compiler is a master of recursive functionality. It takes a while to get your head around how this all can be expressed and accomplished, but it is pretty cool. The internal syntax of a language is often expressed in BNF notation. To create the language compiler, we first create another compiler that understands BNF notation (a simpler language) which then follows the syntax expressed within BNF to create the actual compiler. This tool, as implied, is called a Compiler compiler. Some compiler tools that were commonly used in the past were known as Lex & Yacc (Yet another compiler compiler). This would be a place you could get started. Although I did not use Yacc for gcode++, I did use it in the past to learn the ropes.
I don't want to discourage you from learning compiler writing, but indeed there is a lot going on here. It is not uncommon for individuals to dedicate their entire careers to compiler writing alone. It is a specialty not suited to everyone. However, it is like anything else, once you understand, get your head around it, you got it. Then it is no longer complicated.
By the way, the gcode interpreter will choke on the above code, but gcode++ will accept it and turn it into this:
#<x>=[ 2 ]
#<s>=[ 4 ]
G01 X[ #<x>*2 + 4 ]Y[ #<s>/3 + 2 ]
not that you should write such ugly code to start with, but the compiler doesn't care
Since you have asked, I will try to answer.
The short answer, yes, you are way oversimplifying. The meaning of "parse" and of "compile" are important to understand. Firstly, let me refer you to my document gcode++.pdf on my website. In there I discuss some of the development issues and what constitutes a compiler. Ok, that said,
To parse is to separate into meaningful groupings. In the case of a normal sentence, you could parse out the words using white space to separate them. But that is very simple. If you preparing the text for a compiler, parsing also implies that you recognize what it is that you parsed. You would have to say that this is a "noun", this one is a "verb", etc. so that the compiler, which is going to verify an acceptable syntax, can act on it.
Let's say you had this gcode:
x = 2
s = 4
G01Xx*2+4Ys/3+2
How do you tell, on line 3, what the G code is, which are parameters?, which are numbers, which are the variables?
You get the idea. The parser follows a set of rules to determine the breakout and what each thing is (token). These rules are usually implemented as regular expressions "regex". I have 2 or 3 books on this topic alone.
The compiler receives the stream from the parser and Identifies valid sentences, in the language itself, using the tokens, to translate to the output. But wait? what if the sentence contains other sentences? Suppose you hit an "if" statement. You cannot process that until you know all the statements inside the "if", which may contain other "if" statements, and other blocks of statements, and on and to infinity. You can see, at this point, a recursive nightmare is developing. A compiler is a master of recursive functionality. It takes a while to get your head around how this all can be expressed and accomplished, but it is pretty cool. The internal syntax of a language is often expressed in BNF notation. To create the language compiler, we first create another compiler that understands BNF notation (a simpler language) which then follows the syntax expressed within BNF to create the actual compiler. This tool, as implied, is called a Compiler compiler. Some compiler tools that were commonly used in the past were known as Lex & Yacc (Yet another compiler compiler). This would be a place you could get started. Although I did not use Yacc for gcode++, I did use it in the past to learn the ropes.
I don't want to discourage you from learning compiler writing, but indeed there is a lot going on here. It is not uncommon for individuals to dedicate their entire careers to compiler writing alone. It is a specialty not suited to everyone. However, it is like anything else, once you understand, get your head around it, you got it. Then it is no longer complicated.
By the way, the gcode interpreter will choke on the above code, but gcode++ will accept it and turn it into this:
#<x>=[ 2 ]
#<s>=[ 4 ]
G01 X[ #<x>*2 + 4 ]Y[ #<s>/3 + 2 ]
not that you should write such ugly code to start with, but the compiler doesn't care
The following user(s) said Thank You: tommylight
Please Log in or Create an account to join the conversation.
02 Apr 2022 02:57 #239043
by rodw
My real intent was to show that there are ways to fully integrate gcode++ into a machine controller using the linuxcnc as a platform and there is probably not that much work to achieve this becasue you already convert it to gcode. You would take a block in gcode++, "compile" it to gcode and send the output to the linuxcnc interpreter for processing.
Its not something that I am interested in pursuing. I let my post processors in Sheetcam and Fusion360 create the gcode I need. With my plasma cutter I can output gcode from Sheetcam direct to linuxcnc from my Office on windows and simply click on the load latest button in linuxcnc and its ready to run.
Its not something that I am interested in pursuing. I let my post processors in Sheetcam and Fusion360 create the gcode I need. With my plasma cutter I can output gcode from Sheetcam direct to linuxcnc from my Office on windows and simply click on the load latest button in linuxcnc and its ready to run.
Please Log in or Create an account to join the conversation.
Time to create page: 0.082 seconds