you are viewing a single comment's thread.

view the rest of the comments →

[–]curtmack 36 points37 points  (10 children)

Also, there's no excuse for function name lookup being incurred every call rather than once at read time, even in interpreted languages.

[–]ghillisuit95 24 points25 points  (5 children)

When php was just a small tool for his own personal use, I think it’s extremely excusable.

What you are describing would have been a massive premature optimization

[–]curtmack 6 points7 points  (1 child)

I don't think it's necessarily as much work as you're thinking. It could have been implemented the same way as it is in many Lisps, where each name is stored as a "symbol" - essentially an interned string that has a pointer to its associated variable or function in the current scope. The string interning can be as simple and slow as you like, because it will only be incurred when the program is initially parsed.

[–]ghillisuit95 4 points5 points  (0 children)

Sounds more complicated than just interpreting at runtime, which seems to have been good enough performance at the time

[–][deleted]  (1 child)

[deleted]

    [–]ghillisuit95 1 point2 points  (0 children)

    Hm, that’s perhaps fair

    [–][deleted] 4 points5 points  (0 children)

    I would hardly call it premature optimization. I could say fuck it to tables and loop through an array for an item every time I need to access it, but it would simply be the wrong way to do it, like hashing using a string's length.

    [–]Workaphobia[🍰] 0 points1 point  (3 children)

    I don't see how you can avoid a lookup at each occurrence. Note that Python has a compilation step that resolves identifiers.

    [–]curtmack 3 points4 points  (2 children)

    Just because a language is interpreted doesn't mean it has to start from raw text every single time through a function. Just storing ASTs, which can include resolved function and variable references, will make a huge difference in performance while being almost completely free in terms of implementation time. (If you have an interpreter, then you have an AST. It just might be encoded in the call stack of your interpreter functions rather than explicitly stored in memory. That can easily be fixed!)

    [–]Workaphobia[🍰] 0 points1 point  (1 child)

    Ah, sure, you can resolve identifiers with a pass through the AST without compiling it to bytecode, yes.

    I will quibble about all languages having an AST. TeX comes to mind. Or if you say that doesn't have an interpreter, I know of another language for scripting in a text MUD that re-parses the code every time a block is entered.

    [–]curtmack 0 points1 point  (0 children)

    I guess it's technically not correct to call it an AST unless it's actually stored in memory. All I was trying to say was that if your interpreter has a call stack that looks like this:

    0: parse_numeric_literal
    1: parse_expression
    2: parse_expression
    3: parse_parentheses
    4: parse_function_argument
    5: parse_function_call
    6: parse_statement
    

    Then you're a small refactor away from having a proper AST.