我完全同意上面提到的有關創建AST並在每次迭代中對其進行評估的所有答案。這是迄今爲止做你想做的最好的(也是最正確的)方式。
但我寫了編譯器爲生,我不禁建議另一個有趣的解決方案。當你說你想創建一個接受1個參數並返回結果的「函數」時,我提出了一個額頭。
讓我們試着做到這一點。
我們將開始爲我們的「功能」分配一些內存。
現在讓我們假設4k字節就足夠了。 所以我們開始做
void* my_func = malloc(4k);
現在,這是我們需要使該地區執行真正的功能。這將取決於您的操作系統,您將不得不調用正確的系統調用。 您只需將執行權限授予此頁面即可。
現在我們解析表示表達式的字符串。 我在這裏假設WIN 64 fastcall調用約定。你可以使用你自己的。 所以參數t將在%rcx中,thr的結果將以%rax的形式返回。
現在,讓我們的示例表達 - T * 2 + 5
因此,我們將有總成 -
imulq $2, %rcx, %rcx
addq $5, %rcx
movq %rcx, %rax
retq
現在我們組裝成等效字節這在my_func,並將
所以你會有一些等效的 -
strcpy((char*)my_func, "\x48\x6B\xC9\x02\x48\x83\xC1\x05\x48\x89\C8\C3\0");
而不是一個字符串喲你將擁有建立在解析的緩衝區。 但你明白了。
如果需要更多內存,您可以分配兩倍的大小並複製內容。
最後,所有你所要做的就是打電話給你的內循環「功能」 -
typedef int (*func_type)(int);
for(t=0; t<N; t++)
s=(func_type)(my_func)(t);
雖然這是最不切實際,難以實現方法,我向你保證這會給你最好的性能(假設你生成有效的組裝)。
這是一個有趣的練習不被重視。很高興看到一個庫爲簡單的表達式做這件事。
另外不要忘記釋放你的記憶並移除執行標誌。
編輯:一個半最佳,但容易產生策略將是使用堆棧的所有操作。基本上,一旦解析完成後構建AST,就會從堆棧中彈出每個節點的參數,然後使用寄存器計算結果並將其推回堆棧。最終值可以彈出到%rax中。這個策略對AST的任何運行時間評估都是有效的。 爲您節省了所有的寄存器分配和指令調度的負擔。
除非我遺漏了一些東西,這聽起來像是你只需要一個帶有一個參數的函數,並且它可以在調用時進行計算並返回結果,就像你描述的那樣。這聽起來像你有2個常量,公式保持不變。 – AntonH
如果您在編寫程序時知道您的表達式字符串,請將其轉換爲C函數,然後讓編譯器完成剩下的工作。 – DyZ
用戶輸入功能。它可以是任何東西,但總是有一個變量「t」 –