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

Pages: 1... 910111213... 20
Well, if double d; is 8 bytes and int is 4 bytes than the two halves of double are ((int*)d)[0] /*and*/ ((int*)d)[1] (not sure in which order you should push them). Again. Why would you need this?
I don't know either, lol, but I had the right pushing in my interpreter. Just make two guesses.
Don't use a scalar variable as an array, you won't get the correct byte order that way. Use bitwise operators instead.

[edit] Also, ((int*)d)[1] should be ((int*)&d)[1] or *((int*)&d + 1).
Last edited on
So using a float pointer (instead of int) should work good, shouldn't it?
No, I'm saying don't use a variable like an array if it isn't an array.
Oops about the &. I don't see what's wrong with []s though? Do you mean that as a style thing? This bit of code is only there to copy an 8 byte value on the stack. I am sure that stack has the same endian as the rest of memory, so what could go wrong?
Wow finally it works correctly. Thanks hamsterman, your solution is correct... :)
Start point : My program now is able to call a function e.g printf.

I'm going to add some extra operators and rules, such as ++; --; ^; ^= and (maybe) some bitwise operators.
I guess ++;--; operators perform faster than operator ±=1, and ±=1 performs faster than var = var ± 1. Is it correct?

And again the power operator. Unfortunately in my opinion it may be impossible because the parser calculates every expression in order from left to right. So I cannot reverse, turn back the loop and re-calculate all previous calculated values because it's very slow. Here's an example :
x = 5 * 10 ^ 2

5 * 10 = 50 certainly. With the default parser method, it becomes (5 * 10) ^ 2 then 50 ^ 2 and finally 50 * 50. The output is 2500. (Wrong)

But If I changed the precedence, it would become 5 * (10 ^ 2). First, multiply 5 with 10 we get "50". When result is 50 I have to calculate 10 ^ 2 (= 100) then recover the main value (again : 5), then after that recalculate (multiply 5 with 100 together). That's 500, but this method "kills" performance very quickly.

Is there any better solution guys?
Last edited on
I guess ++;--; operators perform faster than operator ±=1, and ±=1 performs faster than var = var ± 1. Is it correct?
If you're referring to these operators in C/C++, then you are very wrong. Are you aware of such thing as compiler optimization? (Though I'm not even sure what to optimize here...)

About precedences, didn't you solve this problem with 5+10*2. Anyway. You should be able to play with your parse trees a bit.
hamsterman, thank you for pointing it out. Yes. I should play around with my parse trees a bit...
Last edited on
I made an additional function operator which only makes my code easier to read :)

operator[string*]
1
2
3
4
5
inline Data* operator[] (const char *string) {
	unsigned nPos = Search(string);
	if(nPos != -1)return &data[nPos];
	return 0;
}

Example code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
//ClassData classItem

classItem.data.push_back(Data("one",t_Int));
classItem.data.push_back(Data("two",t_Int));
classItem.data.push_back(Data("three",t_Int));

//Accessing a variable...
classItem["one"]->SetValue(1);
classItem["two"]->SetValue(2);
classItem["three"]->SetValue(3);

//Instead of this...
//classItem.data[0].SetValue(1);
//classItem.data[1].SetValue(2);
//classItem.data[2].SetValue(3); 
Last edited on
The average speed loop I see it's usually between 500.000 and 1.000.000, as it performs just about three million operator commands. In my opinion it's still slow because an interpreter has to handle many things with no performance hit. So now assembly vs a portable parser? No need to say more because assembly performance is perfect and most likely it can be optimized by an intelligent complier by many ways, but it's only designed for a specific unique command. And the "portable" certainly has a powerful portable feature. It knows how to understand an unknown code or expression but it handles information very slowly (one is checking characters, one is handling information via complex variables, functions and structures)...

So I'm very confused about that. I have no idea what the recommended speed for an interpreter is. It's really slow, isn't it?

Does anyone have an idea?
Last edited on
I think it would be horrible if I added some advanced features (certainly they're terribly difficult) such as smart pointer, function detector, multiple dimensional array, function returning value, power operator... Because in my point of view they may kill the performance very very quickly.

Now I have some regular operators and I want to sort it (by precedence)

(±); (*); (/); (%); (^); (=);

1st
(^) (power)

2nd
(*); (/);

3rd
(±); (%); (=);


Is it correct? Should my interpreter be divided into three different layers above?
Last edited on
My power operator is going well. So, I think a new precedence doesn't matter, only I have to insert a lot of code in order to achieve the perfect result.

Now I want to get function returning value.
I've just learnt and memorized how to push parameters, call a function, do some basic calculation, and check, jump, and make while-for loop.

Now for example I want to get the final result from the function isdigit , but how to do this? By assembly?
Is it possible if I'm going to make "smart pointer" feature for my intepreter?

I ask this just because I really want the next function scanf to be called properly (by my interpreter)... :)
Last edited on
Jackson Marie wrote:
Now for example I want to get the final result from the function isdigit , but how to do this? By assembly?


The code looks like:


1
2
3
4
5
6
7
8
9
int Result = 0;
int Source = '1';
asm {
    mov eax, (ascii value of the letter to convert)
    push eax
    call isdigit
    (pop ebx, if cdecl)
    mov Result, eax
};


Only works for MSVS, I hope it's correct.
Anyways you should not make it like every function needs its own code to be called.

Jackson Marie wrote:
Is it possible if I'm going to make "smart pointer" feature for my intepreter?

You should make classes in your interpreter to make it look consistent.
I suggest you to leave control to the user, anyways.
Last edited on
Thank you EssGeEich very much but now I got a trouble about stack correcting.

First of all let's take a look :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
int func(int i){return 0;} //Only one parameter

int main()
{
//Input parameters
Input();

//Push parameters (Suppose there are two parameters which are accepted...)
__asm push 10
__asm push 15

__asm call func //Crash !!!
__asm add esp, 8

return 0;
}


The correct version :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
int func(int i){return 0;} //Only one parameter

int main()
{
//Input parameters
Input();

//Push parameters (Suppose there are two parameters which are accepted...)
__asm push 10
__asm push 15

if(number_of_parameters != 1)
{
     __asm clear, stack //Clear all things that the program has just pushed...
     return 0;
}


__asm call func 
__asm add esp, 4

return 0;
}


When the program detected there is a function calling error, for example :
- Missing one or more necessary parameters
- Incorrect stack size,
- Incorrect parameter list - order


...then it would clear the stack and break its function calling. The problem is I could not find any assembly code which is used to clear function stack when any noticeable problem is detected.

Is there any magical code which can do this?
Do you know guys?
Last edited on
I spent about twenty minutes to fix value conversion order.

And, this is conversion rule :
Simplest :
- Integers meet decimals -> decimal
- Low precedence meets higher precedence level : switch to higher level

Value level list :
- bool < char < short < long long < float < double


Wow, that's quite interesting! The program automatically adjusts the main precedence is needed. You may change the default value definition and also can change the main conversion precedence by using type_cast feature. And now with this feature I can write :
1
2
// '0' = 40
'0' + '0' + '0' + '0' // = 160 

What will happen if this expression is performed? Well, it gives -33 - if the main value is unsigned, that's 160. So it needs to be converted, by using type_cast. If you want the interpreter to give the correct value, here is one solution :
[int]'0' + '0' + '0' + '0'

Other examples :
false - true

Certainly the exact value is "-1" but actually result is "1". Just because boolean values only and only accept value "0", or "1".

[char]10 + 10000 / [char]6

10000 is unknown, so the parser will automatically load it as an integer. If the value is 'char', then it causes "Out of range". The value increases the main precedence conversion up to Int level, so generally the result is not affected much except decimal data (is truncated). Result is 176.

10 + [double]10000 / 6

10; 10000; 6 are integers, but 10000 has a double attribute. Because integers have a lower precedence than decimals, so the precedence is switched to decimal. So the value is more accurate - 176.66666...

[int]10.24 + [float]10000 / [char]6.49f

Same value, 176.666...
But it's float, not double. So when I call a function it only takes 4 bytes, rather than a double it takes 8 bytes...

Generally my opinion it's very important because certainly it helps a lot about function calling and correcting... :)

Only a question : If an unsigned value meets a signed value, what will happen? :)
Last edited on
Wow! Finally I completed a very small feature that C++ currently cannot handle.

And now, here is a test example :
10 + (10 > 100) ? 10 : (5 > 50) ? 50 : 100

As you can see, the example has two "?" constructs. And after calculation the result is 100. Why?

- Assign the main variable a value (10)
- (10 > 100) returns 0 (false)
- The false value forces "10" to take the second value (5 > 50)
- But the expression (5 > 50) also is locked because there is another "?" construct.
- Then calculate (5 > 50) and it returns 0 (false)
- The main value now can take the next second value 100...

Similar expression...
(1 > 2) ? (2 > 3) : (3 > 4) ? (4 > 5) : (5 > 6)....

Conclusion : C++ cannot handle these things. :)
My opinion is only "because it's too complex". But let me know your compiler result. What is your result? :)
Last edited on
I got a trouble and I have no idea "what should I do"?

I created a new source file and tried moving a function then re-complied the project. The function I had defined before is from a header file (call_a_function()). And I caught hundreds of linking errors. :C

I only see an error "(object_name) has already existed, found : define.obj"

What do you mean by that? How to fix those errors?

(Any help would be greatly appreciated)
C and C++'s conditional operator is right-associative, but its precedence is very low:
(a+b?c:d?e:f) == ((a+b)?c:(d?e:f))

No one uses this because a) the conditional operator is hard enough to read without the extra help and b) no one remembers its exact precedence and associativity without looking it up.
Last edited on
Pages: 1... 910111213... 20