Comments (30)
I do not support this feature request. Pre-processing can be done outside of Solidity. The C preprocessor is one candidate.
When I read the code for a deployed contract I want to see what was deployed, not a bunch of other stuff that was not deployed.
from solidity.
There is a very standard and very simple solution. The C pre processor.
It does #ifdef
, which is 95% or what's needed everywhere.
Plus everybody already has it already.
But still I'd like to see a concrete use case that is helped by a preprocessor otherwise why is this issue still open?
from solidity.
This issue has been open for a long time and is unlikely to be implemented as is since it's just a loose idea without a concrete spec. I think that the forum is a much better place for a general discussion on the topic so I'm going to close it.
As @ekpyron already said, we think that there are much better alternatives to C-preprocessor-style macros so it's unlikely we'll ever add such a feature to Solidity. We'd be more open to some flavor of syntactic macros but it depends on the details of the proposal so if we get one, we'll comment on it separately (though I'd still recommend asking for feedback on the forum first before going through the effort of writing it all out). For now we think those other features will be enough to cover most practical use cases and the effort is better spent on them.
Preprocessing is also something that's very easily delegated to external tools. Some where already mentioned in this thread. It's even possible to directly use the preprocessor built into a C compiler if anyone really wants that.
from solidity.
Imports in Solidity are not merely text-based preprocessor imports, but semantic imports that even allow renaming of identifiers and introducing module namespaces. So cpp includes are not a replacement for them, nor does the existence of imports bind us to not using external preprocessors for any other macro use cases.
In general, we are moving towards compile-time-constant expression evaluation and support for generic programming in the language, which will be a superior solution to macros in most of their use cases. For anything that may be left (if anything at all), I see little reason to introduce compile-based support compared to asking tooling to allow tying an existing preprocessor like cpp
into the build process.
I'm actually in favour of closing this issue, since macros are not currently planned in the compiler and for any further discussion on the topic, resp. attempts to change our mind on this :-), the forum is the better place.
I just see that @cameel was faster than I :-). Note that solidity imports can change and introduce identifiers and resolve recursive dependencies on the declaration rather than the file level (which is necessary since Solidity does not have forward declarations). There is actually surprisingly little in common between #include's and Solidity's imports :-).
from solidity.
I have one more request as you close this, that you don't introduce any new syntax (eg #) that would break the cpp. No action required, just do no harm plz.
from solidity.
I don't think we can promise that we'll never ever do to that but I can at least say we're currently not planning anything that could break it and would not do it without a good reason. We're going to keep that in mind when designing new features. The chance that we'll have to break it is IMO very low.
from solidity.
This feature sounds interesting . Would people prefer a hygienic syntactic macro system?
from solidity.
Something similar to http://www.sweetjs.org
from solidity.
What I want out of this feature is C-PreProcessor-style macros, and also compiler support to output a flattened file. The import
logic would also live inside of this preprocessor.
from solidity.
@wjmelements input files should not be flattened and not all ways to compile a contract system can be done on a flattened file. preprocessor style macros are also very hard to check, I would not support implementing them as part of the compiler.
from solidity.
Can we close this issue since it provides no syntactical suggestion and it is pretty much useless?
from solidity.
Macro is a very important feature missing in Solidity, it would be incredibly useful for developers when debugging complex code during development.
One way to currently achieve that is to emit a lot of events along a function to map what's going on. example, it's clearly undesirable.
It would be great to have flags that can be active only during development deployments, and not during production for logging events, for instance. Or balancing game mechanics.
In my mind it would also be similar to c macros in addition of taking an env var to define the mode / network it's being deployed to
from solidity.
@flockonus have you tried just using the C preprocessor?
from solidity.
@chriseth i didn't really think of searching outside the language until you ask now.
It seems solpp is a preprocessor for solidity, and looks good, perhaps just missing env var support on compilation (seems easy to add).
The implementation seems to fit a macro system very well, has many features, but it won't work with linters or syntax highlighters since it's not part of the language.
from solidity.
Before considering implementing macro support I would first define what problems it should solve exactly.
I personally don't like the idea of macros at all as they are (often) just another language on top of the language and not type aware at all. And the reason they (usually) exist is the lack of compile-time features of the main language.
If we have such a list of what one wants macros for, we might can translate that into features that could go directly into the Solidity language.
from solidity.
Good point. Personally I constantly run in 2 use cases:
One use case is logging by using events during development, and even changing function modifiers.
Sometimes also makes sense to change time spans, for instance, in production a class could require a freeze period of 1y, but during tests, 10 seconds is enough.
Current workarounds are:
The first is achieved by manually un/commenting a lot of lines.
For the second I create a class to inherit and override params and use that one for tests.
from solidity.
For the first: I don't actually know enough about events and logging to have a useful suggestion here. I leave this one to others for now :>
For the second, a language feature could be something like a way to define global variables that has a default but can be overridden by cmd line parameters (or json input) when compiling.
from solidity.
Sometimes also makes sense to change time spans, for instance, in production a class could require a freeze period of 1y, but during tests, 10 seconds is enough.
This specific sub problem is solved by Truffle for example providing a way to advance time in tests. I think that is a better approach because you are actually testing the production code and not a "for testing only" version.
from solidity.
Regarding events and testing I think test
attributes found in Rust could provide a good example:
#[test]
emit DebugOnlyEvent();
When compiling for release output this code will not be included. However this feature has to be very restricted otherwise has the potential that testing and release binaries differ way to much negating the usefulness of tests.
from solidity.
When I read the code for a deployed contract I want to see what was deployed, not a bunch of other stuff that was not deployed.
Look at the blockchain directly then, not the contract source. Code is high level.
from solidity.
I agree with @fulldecent that preprocessing can be done outside of Solidity.
I still think this is really important because the appropriate use of preprocessors could save millions of dollars or more in gas fees! Because solpp and psol appear to be dead, I think developers should use something else that is STANDARD and SIMPLE so developers don't need to install a bunch of different tools and so that security auditors are not misled by some weird behavior from the preprocessor.
One place to start would be to find some open source contracts that use some kind of preprocessing so that we can see what is in use and what is working well. If there is a clear winner then developers could rewrite the preprocessing for various open source contracts or add it to some contracts that could benefit.
from solidity.
OpenZeppelin wrote their own code generator, and anyone who wants to work on it has to learn TS and figure out how their code works.
from solidity.
But still I'd like to see a concrete use case that is helped by a preprocessor otherwise why is this issue still open?
Macros
Imports
Conditionals
Have you never programmed with macros before? Every language should have them. The alternative is copypaste boilerplate. Have a look at the status quo. Some kind of template code is necessary; macros are the best because they can do more than type substitution.
Suppose you had code like below, which I took from a contract I picked at random.
function totalReleased(IERC20 token) public view returns (uint256) {
return _erc20TotalReleased[token];
}
function shares(address account) public view returns (uint256) {
return _shares[account];
}
function released(address account) public view returns (uint256) {
return _released[account];
}
Most of this code is the same. Should be written only once.
#def get_uint256(field)\
function field(address account) public view returns (uint256) {\
return _ ## field[account];\
}
get_uint256(totalReleased)
get_uint256(shares)
get_uint256(released)
We can also break out the type to make it even more reusable.
#def get_(type, field)\
function field(address account) public view returns (type) {\
return _ ## field[account];\
}
#def get_uint256(field) get_(uint256,field)
Macros can contain other macros, which themselves don't have to be defined. This allows for reuse. Here is a solidity version of some code I wrote in C
#def OPS \
OP(buy, 2, uint256)\
OP(sell, 1, uint256)\
OP(lock, 0, address)\
OP(unlock, 0, address)\
enum ops {
#def OP(name, _, _) name,
OPS
#undef OP
}
#def OP(name, argCount, argType)\
function name(argType[argCount] args) external {\
_do_ ## name(args);\
}
Look at the ways I use OPS
from https://github.com/wjmelements/evm/blob/master/include/ops.h. I redefine OP
7 times. 3 of them are for test cases.
from solidity.
Take a look at my post: https://forum.soliditylang.org/t/feature-request-add-define-to-solidity/430
Most people want to add macros. I think we should close the other issues and work on a specific design.
from solidity.
There is two things going on here. On the one hand, there are usecases in which macros can serve as a poor and less secure replacement for generic programming without type-checking. Our design decision for those cases in the long run is that we will go the route of proper type-checked generics.
Any other cases that may still warrant the use of macros are better addressed outside the compiler e.g. by reusing cpp
as preprocessor. Higher levels of support for that is better requested from tooling than from the compiler itself.
Or does anyone have a good reason why direct macro support by the compiler would be preferable compared to the use of a preprocessor? Is the worry there readability of already preprocessed sources during source verification?
from solidity.
Or does anyone have a good reason why direct macro support by the compiler would be preferable compared to the use of a preprocessor?
solc already does import, one of the main preprocessor actions. Behavior is identical to #import. I would be ok with yall dropping that in favor of the cpp syntax if cpp is the path you want to pursue.
from solidity.
solc already does import, one of the main preprocessor actions. Behavior is identical to #import.
It's not. Preprocessor #include
more or less just dumps content of one file into another, regardless of whether the result makes sense or not. In Solidity the language has proper semantic modules with their own scope.
from solidity.
solc already does import, one of the main preprocessor actions. Behavior is identical to #import.
It's not. Preprocessor
#include
more or less just dumps content of one file into another, regardless of whether the result makes sense or not. In Solidity the language has proper semantic modules with their own scope.
(#import is from Objective-C and differs from #include)
#include does more than dump; it does the cpp evaluation recursively. This allows more than dumping though dumping is the most-common use case, like solidity import.
scoped semantic modules
Are you referring to #pragma?
from solidity.
(#import is from Objective-C and differs from #include)
Ah, sorry, looks like I misunderstood you. I did not consider Obj C and thought it was a typo and that you were referring to #include
from C.
from solidity.
It's fine. We can continue to bolt the cpp onto solc ourselves. I just wish it worked with solidity imports. The flattener project will never die I guess.
from solidity.
Related Issues (20)
- Multiple _ within a function modifier lead to incorrect behavior when via-ir is enabled HOT 1
- Allow modularising yul assembly
- Include mapping parameter names in AST and StorageLayout
- Please allow to encode calls to functions using variable sized arrays/tuples as parameters. HOT 1
- Tag position used instead of tag size to compute size of addresses
- replace `Brownie` with `Ape` HOT 8
- Incorrect `parameterSlots` and `returnSlots` for some methods in `functionDebugData`
- Stack too deep errors with via-IR for some compilation routines
- Enable function overloading resolution when importing specific libraries or free functions via `using for` HOT 1
- `StackCompressor` goes into infinite loop after `SSATransform` on inline assembly with very long chains of dependent assignments HOT 2
- Add blobhash inside the `tx` context: blobhash(uint index) --> tx.blobhash(uint index) HOT 4
- SMTChecker: Use SMT-LIB interface instead of solvers' APIs
- Lack of proper heuristics in the Function Specializer can lead to large contract sizes HOT 5
- build solidity error HOT 3
- When compiling with the `via-ir` option, calldata out-of-bounds causes the transaction to revert HOT 1
- Support for Compiling Solidity to LLVM IR to Facilitate zkVM Adoption?
- Switch default EVM version to Cancun
- Performance issues of `solc --abi --via-ir` HOT 6
- Verifying blobhash causes failure to obtain gasLimit HOT 2
- Security vulnerability: Why do % and MOD result in different outputs despite being technically the same function? HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from solidity.