<p>Some languages like C and C++ require defining the names before using them, though the definition could sometimes be only a header specifying something is a struct or function without the body. Some languages don't. And many interpreted languages are mixed, that you could refer to anything in the definition, but the code must be called after the referred entities are also defined completely.</p>
<p>What are the exact criteria for designing the syntax to make referring before definition possible? And is it possible to have a middle ground, that forward declarations are only required in the situations that it is absolutely necessary?</p>
<p>In the best case, function bodies are just strings, and definitions are scanned before evaluation, making this trivial. In the worst case, you could define new syntax in the code, which may change the position of the end of a function, making this obviously impossible. But where do they meet?</p>
<p>A special example is Bash, where <em>functions</em> are in the mixed way, as they are just called using their names as strings and there isn't a mechanism to track down where they are defined, but <em>aliases</em> must be defined before using in a function, because you could alias unpaired braces or other grouping constructs. It looks like a middle ground, but is greatly simplified because of the fact that Bash is not object oriented. In object oriented languages, object definitions may carry a syntax change from a class elsewhere.</p>

<syntax><parsing>
What are the exact requirements of not requiring forward declarations everywhere?
CC BY-SA 4.0
2023-07-27T23:06:15.710Z
The only real requirement is that your compiler does at least two passes over the source code. In that case, you can find all declarations on the first pass and then use them by name in the second pass. The order that they appear in the source code only matters if you have to find declarations and also do name resolution in the same pass.
kaya3
CC BY-SA 4.0
2023-07-27T23:21:34.723Z
@kaya3-supportthestrike I think aliases in bash could not be referred before definition in any implementation, because you could `alias x={`. You could get similar things if you are going to support two different kind of regexes using different escapes, in grammars like JavaScript, and only distinguish them by the function call. More practically, in C++, the keyword `typename` is sometimes required in random places in templates even with SFINAE. I wonder why it is the case.
user23013
<h1>Multi passes</h1>
<p>Forward declarations are a specific requirement of <em>one pass</em> compilation process. So to <em>not</em> have to forward declare anything, your language is expected to have two or more passes on code or AST to resolve pending names.</p>
<p>C and C++ are special in this case because any previous <code>typedef</code> may <a href="https://langdev.stackexchange.com/a/1769/954">change the parsing of the following expression</a>. Languages with keywords to declare types and functions don't have this extra requirement.</p>
<p>Dynamic languages without type checking and dispatch based purely by names don't need more than one pass because any dispatch occurs by consulting what is basically a global dictionary of names.</p>
<p>But type checking languages, dynamic or static, will need more passes for any reference not declared before use.</p>

CC BY-SA 4.0
2023-07-27T23:20:46.103Z
2023-07-27T23:47:25.860Z
2023-07-27T23:47:25.860Z
André L F S Bacci
CC BY-SA 4.0
2023-07-27T23:28:55.870Z
"Languages with keywords to declare types and functions", did you mean different keywords to declare the two? Of course it would require multiple passes. But I'm also interested in the part that may make C and C++ problematic even with multiple passes.
user23013
CC BY-SA 4.0
2023-07-27T23:47:58.343Z
About keywords, it depends. For example, PHP have both `class` and `function`, but Java and C# have only `class`. For the C/C++ case, I linked another answer with a detailed explanation.
André L F S Bacci
CC BY-SA 4.0
2023-07-28T13:04:54.503Z
The linked answer has some examples, but the problem in C and C++ is specifically that the grammar relies on knowing whether an identifier is a type or a value in several places. So even if you try to do two passes (one to collect the names and another to resolve the references) you will not be able to produce an unambiguous syntax tree until the second pass- and in some cases that means you will not even have an accurate set of names after the first pass.
rpjohnst
# What are the exact requirements of not requiring forward declarations everywhere?
Posted by: username_0 on 2023-07-27
Some languages like C and C++ require defining the names before using them, though the definition could sometimes be only a header specifying something is a struct or function without the body. Some languages don't. And many interpreted languages are mixed, that you could refer to anything in the definition, but the code must be called after the referred entities are also defined completely.

What are the exact criteria for designing the syntax to make referring before definition possible? And is it possible to have a middle ground, that forward declarations are only required in the situations that it is absolutely necessary?

In the best case, function bodies are just strings, and definitions are scanned before evaluation, making this trivial. In the worst case, you could define new syntax in the code, which may change the position of the end of a function, making this obviously impossible. But where do they meet?

A special example is Bash, where *functions* are in the mixed way, as they are just called using their names as strings and there isn't a mechanism to track down where they are defined, but *aliases* must be defined before using in a function, because you could alias unpaired braces or other grouping constructs. It looks like a middle ground, but is greatly simplified because of the fact that Bash is not object oriented. In object oriented languages, object definitions may carry a syntax change from a class elsewhere.
**Tags:** syntax parsing
> **Comments:**
> **username_1**: The only real requirement is that your compiler does at least two passes over the source code. In that case, you can find all declarations on the first pass and then use them by name in the second pass. The order that they appear in the source code only matters if you have to find declarations and also do name resolution in the same pass.  
> **username_0**: @kaya3-supportthestrike I think aliases in bash could not be referred before definition in any implementation, because you could `alias x={`. You could get similar things if you are going to support two different kind of regexes using different escapes, in grammars like JavaScript, and only distinguish them by the function call. More practically, in C++, the keyword `typename` is sometimes required in random places in templates even with SFINAE. I wonder why it is the case.  
---
## 1 answers
### Answer by username_2 on 2023-07-27. Score: 3
# Multi passes

Forward declarations are a specific requirement of *one pass* compilation process. So to *not* have to forward declare anything, your language is expected to have two or more passes on code or AST to resolve pending names.

C and C++ are special in this case because any previous `typedef` may [change the parsing of the following expression](https://langdev.stackexchange.com/a/1769/954). Languages with keywords to declare types and functions don't have this extra requirement.

Dynamic languages without type checking and dispatch based purely by names don't need more than one pass because any dispatch occurs by consulting what is basically a global dictionary of names.

But type checking languages, dynamic or static, will need more passes for any reference not declared before use.
> **Comments:**
> **username_0** (2023-07-27): "Languages with keywords to declare types and functions", did you mean different keywords to declare the two? Of course it would require multiple passes. But I'm also interested in the part that may make C and C++ problematic even with multiple passes.  
> **username_2** (2023-07-27): About keywords, it depends. For example, PHP have both `class` and `function`, but Java and C# have only `class`. For the C/C++ case, I linked another answer with a detailed explanation.  
> **username_3** (2023-07-28): The linked answer has some examples, but the problem in C and C++ is specifically that the grammar relies on knowing whether an identifier is a type or a value in several places. So even if you try to do two passes (one to collect the names and another to resolve the references) you will not be able to produce an unambiguous syntax tree until the second pass- and in some cases that means you will not even have an accurate set of names after the first pass.  
---
