Partially working with nested conditionals.

Some of the conditional-skip code is a bit wrong...
This commit is contained in:
2025-09-16 04:52:29 -04:00
parent a96dbe2953
commit 245099c07a
4 changed files with 163 additions and 11 deletions

View File

@ -7,6 +7,11 @@ static_assert( __cplusplus >= 2023'02 );
namespace namespace
{ {
using namespace std::literals::string_literals; using namespace std::literals::string_literals;
namespace C
{
constexpr bool debug= false or true;
}
} }
namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
@ -21,22 +26,53 @@ namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
{ {
while( not tokens.empty() ) while( not tokens.empty() )
{ {
const auto token= tokens.front(); runWord( next() );
tokens.pop_front();
runWord( token ); if( C::debug ) std::cerr << "After processing stack is now: " << std::endl;
if( C::debug ) std::copy( rbegin( stack ), rend( stack ), std::ostream_iterator< std::string >{ std::cerr, "\n" } );
} }
std::cerr << "Run done with stack at size: " << stack.size() << std::endl; if( C::debug ) std::cerr << "Run done with stack at size: " << stack.size() << std::endl;
}
std::string
StackMachine::next()
{
if( tokens.empty() )
{
throw std::runtime_error{ "FATAL: Token required, no more tokens left." };
}
const auto rv= tokens.front();
tokens.pop_front();
return rv;
} }
void void
StackMachine::runWord( const std::string_view word ) StackMachine::runWord( const std::string_view word )
{ {
if( C::debug ) std::cerr << "Processing token: " << word << std::endl;
const bool inConditional= not conditionals.empty(); const bool inConditional= not conditionals.empty();
if( false ); if( false );
else if( word.empty() ); else if( word.empty() );
else if( word == "@enddef" )
{
if( not definition.has_value() )
{
throw std::runtime_error{ "Stray end of function definition" };
}
if( C::debug ) std::cerr << "Definition of " << definition.value() << " is done. It is: " << std::endl;
if( C::debug ) std::copy( begin( words.at( definition.value() ) ), end( words.at( definition.value() ) ),
std::ostream_iterator< std::string >{ std::cout, "\n" } );
definition= std::nullopt;
}
else if( definition.has_value() )
{
if( C::debug ) std::cerr << "Adding word: " << word << " to function definition: " << definition.value() << std::endl;
words[ definition.value() ].emplace_back( word );
}
else if( inConditional and word == "@else" and currentState != Else ) else if( inConditional and word == "@else" and currentState != Else )
{ {
currentState= Else; currentState= Else;
@ -44,11 +80,18 @@ namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
else if( inConditional and word == "@endif" ) else if( inConditional and word == "@endif" )
{ {
conditionals.pop_back(); conditionals.pop_back();
currentState= resumeConditionals.back();
resumeConditionals.pop_back();
} }
else if( inConditional and currentState != conditionals.back() ) else if( inConditional and currentState != conditionals.back() )
{ {
// Pass (We skip things inside the wrong side) if( word != "@if" )
// TODO: Nested if's won't work, here... {
conditionals.push_back( Skipped );
resumeConditionals.push_back( currentState );
currentState= If;
}
else ; // We skip the statement.
} }
else if( word == "@else" ) else if( word == "@else" )
{ {
@ -63,6 +106,13 @@ namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
auto val= peek(); auto val= peek();
push( std::move( val ) ); push( std::move( val ) );
} }
else if( word == "@swap" )
{
auto a= pop();
auto b= pop();
push( std::move( a ) );
push( std::move( b ) );
}
else if( word == "@drop" ) else if( word == "@drop" )
{ {
std::ignore= pop(); std::ignore= pop();
@ -72,6 +122,14 @@ namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
auto val= pop< Integer >(); auto val= pop< Integer >();
push( val == 0 ? 1 : 0 ); push( val == 0 ? 1 : 0 );
} }
else if( word == "@i_inc" )
{
push( pop< Integer >() + 1 );
}
else if( word == "@i_dec" )
{
push( pop< Integer >() - 1 );
}
else if( word == "@i_add" ) else if( word == "@i_add" )
{ {
const auto lhs= pop< Integer >(); const auto lhs= pop< Integer >();
@ -108,12 +166,31 @@ namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
{ {
const auto val= pop< Integer >(); const auto val= pop< Integer >();
conditionals.push_back( val ? If : Else ); conditionals.push_back( val ? If : Else );
resumeConditionals.push_back( currentState );
currentState= If; currentState= If;
} }
else if( word == "@define" )
{
if( definition.has_value() ) throw std::runtime_error{ "Nested definitions not supported." };
definition= next();
if( C::debug ) std::cerr << "Starting function definition for " << definition.value() << std::endl;
}
else if( word.at( 0 ) == '@' ) else if( word.at( 0 ) == '@' )
{ {
throw std::runtime_error{ "Unknown keyword: `"s + std::string{ word } const std::string invoke{ word.substr( 1 ) };
+ "`" }; if( not words.contains( invoke ) )
{
throw std::runtime_error{ "Unknown keyword: `"s + std::string{ word }
+ "`" };
}
const auto &def= words.at( invoke );
std::copy( rbegin( def ), rend( def ), front_inserter( tokens ) );
if( tokens.size() >= 1000 ) abort();
} }
else else
{ {

View File

@ -42,14 +42,20 @@ namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
using Float= long double; using Float= long double;
std::map< std::string, std::string > words; std::map< std::string, std::vector< std::string > > words;
// Which side of the current conditional to take. // Which side of the current conditional to take.
enum ConditionalState { If, Else }; enum ConditionalState { If, Else, Skipped };
std::vector< ConditionalState > conditionals; std::vector< ConditionalState > conditionals;
std::vector< ConditionalState > resumeConditionals;
ConditionalState currentState; ConditionalState currentState;
std::optional< std::string > definition;
std::ostream &output;
void runWord( std::string_view word ); void runWord( std::string_view word );
std::string pop(); std::string pop();
@ -63,7 +69,7 @@ namespace Dillo::Hydrogen::JavaScriptForge ::detail:: StackMachine_m
template< typename T > template< typename T >
void push( const T &t ); void push( const T &t );
std::ostream &output; std::string next();
public: public:
StackMachine( std::ostream &output= std::cout ); StackMachine( std::ostream &output= std::cout );

43
js4g/factorial.js4 Normal file
View File

@ -0,0 +1,43 @@
@define factorial
@dup
@if
@dup @i_dec
@factorial
@i_mul
@else
@i_inc
@endif
@enddef
6 @factorial
@print
@define fib
@dup
@not
@if
@drop 1
@else
@dup
@i_dec
@not
@if
@drop 1
@else
@i_dec
@dup
@i_dec
@fib
@swap
@fib
@i_add
@endif
@endif
@enddef
8 @fib @print
10 @factorial
@print

26
js4g/fib.js4 Normal file
View File

@ -0,0 +1,26 @@
@define fib
@dup
@not
@if
@drop 1
@else
@dup
@i_dec
@not
@if
@drop 1
@else
@i_dec
@dup
@i_dec
@fib
@swap
@fib
@i_add
@endif
@endif
@enddef
9 @dup @print @fib @print