New child language - (Function member address (structure))

Pages: 1... 1011121314... 20
helios...Sorry, that's a mistake I made....

- The main value now can take the next second value 100...

That's totally wrong if we re-calculate the expression. It should be modified, like this :
- The main value now can perform its addition operator (+) with next second value 100...
Then the value is 110, not 100

That result because my algorithm has some problems, it deletes the main variable expression for no reason :)

The next step is multiple dimensional array, I temporarily take back multiple sources effect because I cannot fix the crazy linking error. Here is one of many definitions that the compiler always blocks (header file) :
1
2
//header
char operatorSymbol[NUMBER_OF_OPERATORS] = {'+', '-', '*', '/', '%', '^', '?','&', '|'};


1
2
3
//Expression.cpp
#include "data_definition.h"
//code... 


1
2
3
//Function.cpp
#include "data_definition.h"
//code... 


And here are linking errors :

Expression.obj : error LNK2005: "char * operatorSymbol" (?operatorSymbol@@3PAHA)
already defined in data_definition.obj

Function.obj : error LNK2005: "char * operatorSymbol" (?operatorSymbol@@3PAHA)
already defined in data_definition.obj

main.obj : error LNK2005: "char * operatorSymbol" (?operatorSymbol@@3PAHA)
already defined in data_definition.obj


How to fix those errors guys?...
Last edited on
Declare in header.hpp
Define in source.cpp
Oh thanks L B! I'll try it out.

I've just done variable data definition. Basically this includes : int, long, double, char, short, float and some attributes (unsigned, signed). As same as C++, my variable definition has the same syntax, only it handles a single variable name per expression (If you want to define more, simply put a comma operator between them). Here is an example :
 
char *expression = "int character = 30";

Instead of this :
1
2
classItem.push_variable_back("character" ,t_int);
char *expression = "character = 30" 


And how to define multiple variables in a line :

int a = 1, int b = 2, int c = 3, unsigned int d = a + b + c

When you wrongly define a duplicate variable, no problem! In this case the parser only needs to ignore the request command.

int a = 10, int a = 20

The second request int a is ignored - The value a will be added onto stack instead.

I successfully added several functions such as exit(), getch(), getche(), which don't have any parameter. About stack problem, I have an idea. Instead of wasting my time for hunting assembly code, I only need to define a function which does nothing. And the magical function is :

inline void call_me_haha(...){}

This is a very simple trick and it's used to avoid fatal errors. After calling this function with only a simple call assembly code the program will automatically clear the stack... And the problem has been solved successfully!!! :)

About functions, the parser now can handle and call multiple functions at a time. The comma operator actually is a terminator sign, so also you can write multiple functions in a line. And combine this with variable definition feature :

1
2
3
4
char string* = "char character,\
                        printf(\"Enter a character : \"),\
                        character = getche(),
                        printf(\"\nThe character code you've input : %d\n\",character)";

My first very simple program which is done by my interpreter...

And about speed problem, in short i'm very confused about vector accessing speed.

Which is faster guys :

Loop counting :

1. iterator

2. operator [] (current)

Access first element :

1. front()

2. operator [0] (current)

Access last element :

1. back() (current)

2. operator [vector::size() - 1]
Last edited on
Oh, I spent my previous entire day only for fixing the crazy function calling error.... :(

I have no idea and now still confused although the problem has been solved :
Correct code :
__asm call dword ptr ExitProcess

My expression :
char *string = "ExitProcess(10)"

My old code before :
1
2
__asm call ExitProcess
__asm add esp, 4


The generated code by the compiler : (Test ExitProcess(10))
1
2
3
4
5
__asm mov eax, 10
__asm push eax
__asm call dword ptr ExitProcess
__asm cmp esi, esp
__asm call __chkesp


There isn't any function "__chkesp". I inserted dword ptr but no luck :(
Obviously there is something wrong elsewhere. And finally in short the code runs well since I removed the pop command... :)

I'm confused because there are two different call modes. Here are some examples :
1
2
3
4
5
6
7
8
__asm call exit
__asm add esp, 4

__asm call printf
__asm add esp, 4

__asm call dword ptr MessageBox
__asm call dword ptr ExitProcess

Why they are so different? I have no idea about the word dword ptr. While :

__asm call printf //runs well

Then :

__asm call dword ptr printf //Crash!!!

While :

__asm call dword ptr MessageBoxA //runs well

Then :

__asm call MessageBoxA //Crash!!!

Can anyone explain this?
Thanks.
im unaware.
Ok, and I now added successfully "compound assignment" feature...
In my opinion they are used to modify the value of a variable by performing an operation on the value currently stored in that variable.

Basically my expression syntax it looks like :

- Syntax : variable <operator>= <expression>

- Supported operators : (+); (-); (*); (/); (%); (^);

And here are some examples :
value += <expression>

This expression is equivalent to :
value = value + <expression>

value *= 10 + 5

This expression is equivalent to :
value = value * (10 + 5)

Looks very friendly, right? :)

Note : This feature certainly doesn't work if we assign the first value slot (first-main variable) with a r-value (regular value). Or the variable you specified does not exist.

Simple example :

10 *= 8 + 10

The parser automatically replaces it with :

10 * 8 + 10 //In this case compound assignment is illegal

var *= 8 + 10

If the var variable does not exist, then the parser will automatically replace it with :

8 + 10

Also I've just included two operators, they are increase and decrease operators (++; --;). They are equivalent to +=1 or -=1. So as you can see they are shortened; however, unfortunately, the speed of these operators are totally different :

I measured these operators and here is my result :
CPU : About 3 GHz...

1
2
3
4
5
var++;var--; //Fastest - 2.900.000 operators per second

var+=1;var-=1; //Average - 1.700.000 operators per second

var= var + 1;var = var - 1; //Slowest - 1.100.000 operators per second 

Limitation :
The first example : Only takes a single operator. Any other operation is ignored; except the comma operator.

The second example : It's not the fastest; however, it's the most convenient way. And it seems var+=2 is faster a bit than the fastest one... :)

The third example : Certainly it's slowest; If you want the parser to do this calculation properly, most likely you have to wrap code into two parentheses symbols, for safety :

var = var <operator> (expression)

And then it's not a recommended choice.

What do think about this? Any suggestion?
Last edited on
Why do three trivially equivalent expressions have such wildly varying costs?
helios wrote:
Why do three trivially equivalent expressions have such wildly varying costs?


So the first example, simply the parser only performs a single object, so it's the fastest. (++;--; are too easy to understand so no need to create a stack) :)

In the second example, the parser has to create a calculator stack to handle an unknown expression. Slower a bit but very effective.

The third example, the parser has to do three things :
1. - Find the main variable (var)
2. - Create a calculator stack
3. - Parse the expression (In this case objects are var and "1")

Then the second example it only takes a single object ("1") so certainly it's faster. The third example is longer, and also it has more objects than the second example. Conclusion it's slowest, and if you want to use compound assignment, I recommend you don't use this.
Suppose I told you "close the door", and you went and closed the door, but if I said "shut the door", you decided to climb the building from the outside all the way to the rooftop, then ran down the stairs back to this floor and then came back inside and finally shut the door.
While I can understand why one thing would take you longer than the other, I can't understand why someone would choose the latter approach.
Suppose I told you "close the door", and you went and closed the door, but if I said "shut the door", you decided to climb the building from the outside all the way to the rooftop, then ran down the stairs back to this floor and then came back inside and finally shut the door.
While I can understand why one thing would take you longer than the other, I can't understand why someone would choose the latter approach.
lol... :)
I added const attribute for variable definition.

You may write :
const <type> <variable_name>

Again, the compound assignment may not work if the variable attribute is const, instead of this it will be converted to a r-value instead.

So suppose that we have a variable which has its value 10, consider this :

const int var = 10, var *= 11 + 2

var is const, so certainly compound assignment is illegal. But the parser may replace this expression with :

const int var = 10, var * 11 + 2

Hence the result is 10 * 11 + 2 = 112, but certainly the var variable is never changed.

I've just skimmed a topic "auto type variable". Wow, of course that's very useful. But before implementing this, how? And is this possible? :)

Also I'm still testing and completing variable definition. Now the current feature is for one dimensional variable array. Generally that's difficult because if this type of operation is executed, you have to build and set up its settings for all elements. So if you define :

int var[100];

I think the parser will create a 100 for loops to set up all var's elements.

Conclusion "One dimensional array" is almost done, and the problem now is how to build multiple dimensional arrays.
Clearly in short my first idea is creating a vector container to store and handle all bracket expressions through recorded string positions. Second, after successfully parsing an variable element [position], then check the variable and find the nearest bracket expression.

Accessing a certain variable also is totally difficult; Basically if the variable type is double, or int, then it doesn't matter; But like I mentioned before, the variable data :

1
2
3
4
5
6
7
8
9
10
11
12
13
struct _variable_data
{
union{
	double fValue;
	char chr[8];
	short wchr[4];

	char *lpchar;
	short *lpshort;
	double *lpdouble;
};
enum enum_variable_type type;bool bUnsigned;bool bConst;
};

Only one thing I annoyed is accessing a small element (char; short) is very very slow. What is the cause? Here is my algorithm which gets a small value via an array index :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
inline int getSmallValue(int nIndex)
{
int nValue_Index = 0; 
int nElementIndex;

	if(type == t_Short) // Each primary value holds 4 short values
{
	nIndex -= 4; //First primary element

	while(nIndex > 0){
		nIndex -= 4;
		nValue_Index++; //Next 8-byte element
	}
	nElementIndex = -nIndex;
	return value[nValue_Index].wchr[nElementIndex];
}
else if(type == t_Char) // Each primary value holds 8 char values
{
	nIndex -= 8; //First primary element

	while(nIndex > 0){
		nIndex -= 8;
		nValue_Index++; //Next 8-byte element
	}
	nElementIndex = -nIndex;
	return value[nValue_Index].chr[nElementIndex];
}

return 0;
}


Compare this :
1
2
3
4
inline double getPrimaryValue(int nIndex)
{
	return value[nIndex].fValue;
}


While this code below :

value[10]++ //value = (int)

In short the speed is 2.500.000, then :

value[10]++ //value = (short)

"Speed" decreases wildly, only about 1.000.000...

I'm very confused... What is wrong guys? :(
Seems to me that this thread would be better suited in a blog since you don't seem to be asking questions or accepting the advice given.
Also I'm kinda tired of seeing this topic pop-up in 'My Topics' - Any workaround maybe?
closed account (3qX21hU5)
I believe you can unsubscribe from this topic to remove it from your topics not sure though. But I agree might want to consider getting yourself a blog since it seems like your posts are mostly updates and not questions
Zereo wrote:
I believe you can unsubscribe from this topic to remove it from your topics not sure though.

Yes, they are update news. Some of this are questions really.

I personally agree with you, it is better if the feature you mentioned above is added (as soon as possible) (Just because they may make you annoyed if you don't like :))

And also like naraku9333 said before, making a blog is a good idea, but I think just about one, or two weeks later, my first child debug version will be released...

Once again, I am sorry.
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

The question, "What is the problem which causes the parser accesses small variables (such as char, short) very slowly?" Is my algorithm ok? It seems my function needs a lot of improvements.

The important question about function : What do you think about special type-cast level 3?
Wow, it's hard to explain. Let's say :

LEVEL 1 : The parser casts type for a new member immediately after a new member value is successfully inserted.

Example :
true + '0' + 100 + 100.0f + 100.0

The following variables above will be added with its type-cast :
- true : boolean
- 100 : int
- 100.0f : float
- 100.0 : double

LEVEL 2 : The parser browses all members, chooses the best suit type, then uses its general type-cast to handle and perform its calculation.

true + false + '0' - [int] false - false

The parser has to calculate this expression above, it uses type-cast information to convert the final value of the calculation to a correct value before ending the algorithm.

- true : current_type = boolean
- false : (boolean == boolean) -> boolean
- '0' : (boolean < char) -> type = char
- [int] false : (char < int) -> type = int
- false : (int > boolean) -> int

The value is 49, and the final value is (int) 49 = 49

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
LEVEL 3 (I think it only works with functions) :
The parser will use one sign symbol to control the automatic type-cast browser. That means users can set quickly their own general type-cast for a series of parameters at a time; decide what type of the final value that people should look.

- Syntax : [#parameter_list]
- Example : [#idci] (int, double, char , int)


To be more detailed, consider this :

var = pow (2.0 , 3.0);

As you can see, both 2.0; 3.0 are double. The function has two parameters with total 16 bytes stack. Normally you may write :

var = pow (2 , 3); // They are int

Or even the example :

var = pow (true , 'a'); // boolean, char

Still works correctly... why?
Just because C++ has a powerful type-cast feature. It searches available function templates for parameter information and then uses them to cast the input values to correct values before calling without causing any problem.

With two examples above, simply the compiler replaces the value with :

double pow (double, double);

var = pow ((double)2 , (double)3); var = pow ((double)true , (double)'a');

But about my interpreter? No function templates, then how can the interpreter know what you are doing? It doesn't know how to cast a parameter value. Simply push, pop, then a crash error begins... :(

Problem example : var = pow (2 + 2 , 3.0); "2 + 2" is an int; 3.0 is a double -> Two parameters with 12-bytes stack (It should be 16)

So if you don't know what you are doing, your program will always be in danger when it calls a function.

If you know the syntax :

1
2
int value = 10,
value = pow([double]value, 2.0)


Then no problem. But only forgetting the [double] :

1
2
int value = 10,
value = pow(value, 2.0) //It collapses the program anyway!!!!!!!! 


Therefore now, here is the first solution :

The first solution simply is using the basic type-cast feature.

var = pow([double]2, 3.0)

You are allowed to comment inside the bracket with "_"; if the comment is not a expression. It's convenient, but in some cases it may make you confused if you have to handle a complex expression, in my opinion it looks very ugly.

var = pow([double](3 + 4 + (3 * 15)), [double]2)

And I decided; my opinion - idea is using the symbol "#" to quickly solve the problem.

An example solution :

var = pow([#dd]6, 2.0f)

After # sign there are two special characters.

This tells the first character (first parameter) where it stands it's a double, and also the second character says it must be a double value.
- First character -> First parameter : double
- Second character -> Second parameter : double

So it's equivalent to :

var = pow([double]6, [double]2.0f)

Another example :
var = func([#iicdf]10.0f , 20, 30.00, 40, 50)

The first character (first parameter) must be an int, the second also is an int, the third character now is a char, the forth character says it's a double, and the last character holds a float.

So it's equivalent to :

var = func([int]10.0f, [int]20, [char]30.00, [double]40, [float]50)


What you do think about this idea? Any opinion, improvement or suggestion? : )
Last edited on
Zereo wrote:
I believe you can unsubscribe from this topic to remove it from your topics not sure though

I think Subscribing is about receiving emails (Look at the bottom of the page, in the "Tracking options for this topic:" field), and, yeah, I tried to look around for that but nothing... Anyways it's not really so bad, it's just that I find wrong to make such a big thing with so much help of other people - Not that you cannot get help, but this started like:

I got an idea. This idea is creating my own programming language [...]
What do you think? Share with me your opinions and ideas

And, being in Lounge, that was all right, but then it got filled with code and script quotes which, after 12 pages of topic, are getting really annoying, and, nothing personal but I'm just clicking on the 'New' image every time to get it in a "I've seen you"-state and ignoring what was actually written.

This doesn't mean I won't help you in other topics, but this topic has gotten too big I'm ignoring posts most of the times.
Ditto. Personally, I don't think it would be so bad if JM didn't appear to ignore replies. The flow of information in this thread has been one-directional for the most part.
EssGeEich...

Do you know, until now they are just beginning. The basic information, code style, and syntax remain, and I'm going to divide it into two big categories, Debug - Release version. The original version will be released soon then forgotten. And, also my interpreter has not been named yet. In short I'm preparing.

And I'm ignoring replies? That's too soon to decide. Some people recommended me I should make my interpreter by assembly language but I think it may be a very long time. Making an interpreter certainly takes a plenty of time. So, it's a challenge, and I have to choose the best suit choice to implement them smartly, rapidly and effectively (Even I'm aware that the speed may become very slow). If the general version works correctly and no problem, then I will close this thread and (maybe) start an another topic with my new stage. :)
Jackson Marie wrote:
EssGeEich... [...] Some people recommended me I should make my interpreter by assembly language


Lol, it was me probably, but I didn't say to use ONLY assembly but use C++ and inline assembly.

JacksonMarie wrote:
And I'm ignoring replies?
<Put random phrase here, as long as it's a reply></endOfJoke>

Jackson Marie wrote:
I'm going to divide it into two big categories, Debug - Release version

Useless, does it change anything from debug to release compilation? I guess not, except for an eventual 'debug' keyword on the title's name.

Jackson Marie wrote:
In short I'm preparing.
D:
Some people recommended me I should make my interpreter by assembly language but I think it may be a very long time.
What was said was to interpret an Assembly language, not to write an interpreter in Assembly language.
Subtle difference. One of the two is, in principle, rather pointless.
Pages: 1... 1011121314... 20