Safetensors
GGUF
Turkish
llama
Llama-3
instruct
finetune
chatml
gpt4
synthetic data
distillation
function calling
json mode
axolotl
roleplaying
chat
Instructions to use tda45/TdAI with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- llama-cpp-python
How to use tda45/TdAI with llama-cpp-python:
# !pip install llama-cpp-python from llama_cpp import Llama llm = Llama.from_pretrained( repo_id="tda45/TdAI", filename="llama.cpp/models/ggml-vocab-aquila.gguf", )
output = llm( "Once upon a time,", max_tokens=512, echo=True ) print(output)
- Notebooks
- Google Colab
- Kaggle
- Local Apps Settings
- llama.cpp
How to use tda45/TdAI with llama.cpp:
Install (macOS, Linux)
curl -LsSf https://llama.app/install.sh | sh # Start a local OpenAI-compatible server with a web UI: llama serve -hf tda45/TdAI # Run inference directly in the terminal: llama cli -hf tda45/TdAI
Install from WinGet (Windows)
winget install llama.cpp # Start a local OpenAI-compatible server with a web UI: llama serve -hf tda45/TdAI # Run inference directly in the terminal: llama cli -hf tda45/TdAI
Use pre-built binary
# Download pre-built binary from: # https://github.com/ggerganov/llama.cpp/releases # Start a local OpenAI-compatible server with a web UI: ./llama-server -hf tda45/TdAI # Run inference directly in the terminal: ./llama-cli -hf tda45/TdAI
Build from source code
git clone https://github.com/ggerganov/llama.cpp.git cd llama.cpp cmake -B build cmake --build build -j --target llama-server llama-cli # Start a local OpenAI-compatible server with a web UI: ./build/bin/llama-server -hf tda45/TdAI # Run inference directly in the terminal: ./build/bin/llama-cli -hf tda45/TdAI
Use Docker
docker model run hf.co/tda45/TdAI
- LM Studio
- Jan
- Ollama
How to use tda45/TdAI with Ollama:
ollama run hf.co/tda45/TdAI
- Unsloth Studio
How to use tda45/TdAI with Unsloth Studio:
Install Unsloth Studio (macOS, Linux, WSL)
curl -fsSL https://unsloth.ai/install.sh | sh # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for tda45/TdAI to start chatting
Install Unsloth Studio (Windows)
irm https://unsloth.ai/install.ps1 | iex # Run unsloth studio unsloth studio -H 0.0.0.0 -p 8888 # Then open http://localhost:8888 in your browser # Search for tda45/TdAI to start chatting
Using HuggingFace Spaces for Unsloth
# No setup required # Open https://huggingface.co/spaces/unsloth/studio in your browser # Search for tda45/TdAI to start chatting
- Atomic Chat new
- Docker Model Runner
How to use tda45/TdAI with Docker Model Runner:
docker model run hf.co/tda45/TdAI
- Lemonade
How to use tda45/TdAI with Lemonade:
Pull the model
# Download Lemonade from https://lemonade-server.ai/ lemonade pull tda45/TdAI
Run and chat with the model
lemonade run user.TdAI-{{QUANT_TAG}}List all available models
lemonade list
| namespace pre_wgsl { | |
| //============================================================== | |
| // Options | |
| //============================================================== | |
| struct Options { | |
| std::string include_path = "."; | |
| std::vector<std::string> macros; | |
| }; | |
| //============================================================== | |
| // Utility: trim | |
| //============================================================== | |
| static std::string trim(const std::string & s) { | |
| size_t a = 0; | |
| while (a < s.size() && std::isspace((unsigned char) s[a])) { | |
| a++; | |
| } | |
| size_t b = s.size(); | |
| while (b > a && std::isspace((unsigned char) s[b - 1])) { | |
| b--; | |
| } | |
| return s.substr(a, b - a); | |
| } | |
| static std::string trim_value(std::istream & is) { | |
| std::ostringstream ss; | |
| ss << is.rdbuf(); | |
| return trim(ss.str()); | |
| } | |
| static bool isIdentChar(char c) { | |
| return std::isalnum(static_cast<unsigned char>(c)) || c == '_'; | |
| } | |
| static bool endsWithContinuation(const std::string & line) { | |
| size_t i = line.size(); | |
| while (i > 0 && std::isspace((unsigned char) line[i - 1])) { | |
| i--; | |
| } | |
| return i > 0 && line[i - 1] == '\\'; | |
| } | |
| static void stripContinuation(std::string & line) { | |
| size_t i = line.size(); | |
| while (i > 0 && std::isspace((unsigned char) line[i - 1])) { | |
| i--; | |
| } | |
| if (i > 0 && line[i - 1] == '\\') { | |
| line.erase(i - 1); | |
| } | |
| } | |
| static std::string expandMacrosRecursiveInternal(const std::string & line, | |
| const std::unordered_map<std::string, std::string> & macros, | |
| std::unordered_set<std::string> & visiting); | |
| static std::string expandMacroValue(const std::string & name, | |
| const std::unordered_map<std::string, std::string> & macros, | |
| std::unordered_set<std::string> & visiting) { | |
| if (visiting.count(name)) { | |
| throw std::runtime_error("Recursive macro: " + name); | |
| } | |
| visiting.insert(name); | |
| auto it = macros.find(name); | |
| if (it == macros.end()) { | |
| visiting.erase(name); | |
| return name; | |
| } | |
| const std::string & value = it->second; | |
| if (value.empty()) { | |
| visiting.erase(name); | |
| return ""; | |
| } | |
| std::string expanded = expandMacrosRecursiveInternal(value, macros, visiting); | |
| visiting.erase(name); | |
| return expanded; | |
| } | |
| static std::string expandMacrosRecursiveInternal(const std::string & line, | |
| const std::unordered_map<std::string, std::string> & macros, | |
| std::unordered_set<std::string> & visiting) { | |
| std::string result; | |
| result.reserve(line.size()); | |
| size_t i = 0; | |
| while (i < line.size()) { | |
| if (isIdentChar(line[i])) { | |
| size_t start = i; | |
| while (i < line.size() && isIdentChar(line[i])) { | |
| i++; | |
| } | |
| std::string token = line.substr(start, i - start); | |
| auto it = macros.find(token); | |
| if (it != macros.end()) { | |
| result += expandMacroValue(token, macros, visiting); | |
| } else { | |
| result += token; | |
| } | |
| } else { | |
| result += line[i]; | |
| i++; | |
| } | |
| } | |
| return result; | |
| } | |
| static std::string expandMacrosRecursive(const std::string & line, | |
| const std::unordered_map<std::string, std::string> & macros) { | |
| std::unordered_set<std::string> visiting; | |
| return expandMacrosRecursiveInternal(line, macros, visiting); | |
| } | |
| //============================================================== | |
| // Tokenizer for expressions in #if/#elif | |
| //============================================================== | |
| class ExprLexer { | |
| public: | |
| enum Kind { END, IDENT, NUMBER, OP, LPAREN, RPAREN }; | |
| struct Tok { | |
| Kind kind; | |
| std::string text; | |
| }; | |
| explicit ExprLexer(std::string_view sv) : src(sv), pos(0) {} | |
| Tok next() { | |
| skipWS(); | |
| if (pos >= src.size()) { | |
| return { END, "" }; | |
| } | |
| char c = src[pos]; | |
| // number | |
| if (std::isdigit((unsigned char) c)) { | |
| size_t start = pos; | |
| while (pos < src.size() && std::isdigit((unsigned char) src[pos])) { | |
| pos++; | |
| } | |
| return { NUMBER, std::string(src.substr(start, pos - start)) }; | |
| } | |
| // identifier | |
| if (std::isalpha((unsigned char) c) || c == '_') { | |
| size_t start = pos; | |
| while (pos < src.size() && (std::isalnum((unsigned char) src[pos]) || src[pos] == '_')) { | |
| pos++; | |
| } | |
| return { IDENT, std::string(src.substr(start, pos - start)) }; | |
| } | |
| if (c == '(') { | |
| pos++; | |
| return { LPAREN, "(" }; | |
| } | |
| if (c == ')') { | |
| pos++; | |
| return { RPAREN, ")" }; | |
| } | |
| // multi-char operators | |
| static const char * two_ops[] = { "==", "!=", "<=", ">=", "&&", "||", "<<", ">>" }; | |
| for (auto op : two_ops) { | |
| if (src.substr(pos, 2) == op) { | |
| pos += 2; | |
| return { OP, std::string(op) }; | |
| } | |
| } | |
| // single-char operators | |
| if (std::string("+-*/%<>!").find(c) != std::string::npos) { | |
| pos++; | |
| return { OP, std::string(1, c) }; | |
| } | |
| // unexpected | |
| pos++; | |
| return { END, "" }; | |
| } | |
| private: | |
| std::string_view src; | |
| size_t pos; | |
| void skipWS() { | |
| while (pos < src.size() && std::isspace((unsigned char) src[pos])) { | |
| pos++; | |
| } | |
| } | |
| }; | |
| //============================================================== | |
| // Expression Parser (recursive descent) | |
| //============================================================== | |
| class ExprParser { | |
| public: | |
| ExprParser(std::string_view expr, | |
| const std::unordered_map<std::string, std::string> & macros, | |
| std::unordered_set<std::string> & visiting) : | |
| lex(expr), | |
| macros(macros), | |
| visiting(visiting) { | |
| advance(); | |
| } | |
| int parse() { return parseLogicalOr(); } | |
| private: | |
| ExprLexer lex; | |
| ExprLexer::Tok tok; | |
| const std::unordered_map<std::string, std::string> & macros; | |
| std::unordered_set<std::string> & visiting; | |
| void advance() { tok = lex.next(); } | |
| bool acceptOp(const std::string & s) { | |
| if (tok.kind == ExprLexer::OP && tok.text == s) { | |
| advance(); | |
| return true; | |
| } | |
| return false; | |
| } | |
| bool acceptKind(ExprLexer::Kind k) { | |
| if (tok.kind == k) { | |
| advance(); | |
| return true; | |
| } | |
| return false; | |
| } | |
| int parseLogicalOr() { | |
| int v = parseLogicalAnd(); | |
| while (acceptOp("||")) { | |
| int rhs = parseLogicalAnd(); | |
| v = (v || rhs); | |
| } | |
| return v; | |
| } | |
| int parseLogicalAnd() { | |
| int v = parseEquality(); | |
| while (acceptOp("&&")) { | |
| int rhs = parseEquality(); | |
| v = (v && rhs); | |
| } | |
| return v; | |
| } | |
| int parseEquality() { | |
| int v = parseRelational(); | |
| for (;;) { | |
| if (acceptOp("==")) { | |
| int rhs = parseRelational(); | |
| v = (v == rhs); | |
| } else if (acceptOp("!=")) { | |
| int rhs = parseRelational(); | |
| v = (v != rhs); | |
| } else { | |
| break; | |
| } | |
| } | |
| return v; | |
| } | |
| int parseRelational() { | |
| int v = parseShift(); | |
| for (;;) { | |
| if (acceptOp("<")) { | |
| int rhs = parseShift(); | |
| v = (v < rhs); | |
| } else if (acceptOp(">")) { | |
| int rhs = parseShift(); | |
| v = (v > rhs); | |
| } else if (acceptOp("<=")) { | |
| int rhs = parseShift(); | |
| v = (v <= rhs); | |
| } else if (acceptOp(">=")) { | |
| int rhs = parseShift(); | |
| v = (v >= rhs); | |
| } else { | |
| break; | |
| } | |
| } | |
| return v; | |
| } | |
| int parseShift() { | |
| int v = parseAdd(); | |
| for (;;) { | |
| if (acceptOp("<<")) { | |
| int rhs = parseAdd(); | |
| v = (v << rhs); | |
| } else if (acceptOp(">>")) { | |
| int rhs = parseAdd(); | |
| v = (v >> rhs); | |
| } else { | |
| break; | |
| } | |
| } | |
| return v; | |
| } | |
| int parseAdd() { | |
| int v = parseMult(); | |
| for (;;) { | |
| if (acceptOp("+")) { | |
| int rhs = parseMult(); | |
| v = (v + rhs); | |
| } else if (acceptOp("-")) { | |
| int rhs = parseMult(); | |
| v = (v - rhs); | |
| } else { | |
| break; | |
| } | |
| } | |
| return v; | |
| } | |
| int parseMult() { | |
| int v = parseUnary(); | |
| for (;;) { | |
| if (acceptOp("*")) { | |
| int rhs = parseUnary(); | |
| v = (v * rhs); | |
| } else if (acceptOp("/")) { | |
| int rhs = parseUnary(); | |
| v = (rhs == 0 ? 0 : v / rhs); | |
| } else if (acceptOp("%")) { | |
| int rhs = parseUnary(); | |
| v = (rhs == 0 ? 0 : v % rhs); | |
| } else { | |
| break; | |
| } | |
| } | |
| return v; | |
| } | |
| int parseUnary() { | |
| if (acceptOp("!")) { | |
| return !parseUnary(); | |
| } | |
| if (acceptOp("-")) { | |
| return -parseUnary(); | |
| } | |
| if (acceptOp("+")) { | |
| return +parseUnary(); | |
| } | |
| return parsePrimary(); | |
| } | |
| int parsePrimary() { | |
| // '(' expr ')' | |
| if (acceptKind(ExprLexer::LPAREN)) { | |
| int v = parse(); | |
| if (!acceptKind(ExprLexer::RPAREN)) { | |
| throw std::runtime_error("missing ')'"); | |
| } | |
| return v; | |
| } | |
| // number | |
| if (tok.kind == ExprLexer::NUMBER) { | |
| int v = std::stoi(tok.text); | |
| advance(); | |
| return v; | |
| } | |
| // defined(identifier) | |
| if (tok.kind == ExprLexer::IDENT && tok.text == "defined") { | |
| advance(); | |
| if (acceptKind(ExprLexer::LPAREN)) { | |
| if (tok.kind != ExprLexer::IDENT) { | |
| throw std::runtime_error("expected identifier in defined()"); | |
| } | |
| std::string name = tok.text; | |
| advance(); | |
| if (!acceptKind(ExprLexer::RPAREN)) { | |
| throw std::runtime_error("missing ) in defined()"); | |
| } | |
| return macros.count(name) ? 1 : 0; | |
| } else { | |
| // defined NAME | |
| if (tok.kind != ExprLexer::IDENT) { | |
| throw std::runtime_error("expected identifier in defined NAME"); | |
| } | |
| std::string name = tok.text; | |
| advance(); | |
| return macros.count(name) ? 1 : 0; | |
| } | |
| } | |
| // identifier -> treat as integer, if defined use its value else 0 | |
| if (tok.kind == ExprLexer::IDENT) { | |
| std::string name = tok.text; | |
| advance(); | |
| auto it = macros.find(name); | |
| if (it == macros.end()) { | |
| return 0; | |
| } | |
| if (it->second.empty()) { | |
| return 1; | |
| } | |
| return evalMacroExpression(name, it->second); | |
| } | |
| // unexpected | |
| return 0; | |
| } | |
| int evalMacroExpression(const std::string & name, const std::string & value) { | |
| if (visiting.count(name)) { | |
| throw std::runtime_error("Recursive macro: " + name); | |
| } | |
| visiting.insert(name); | |
| ExprParser ep(value, macros, visiting); | |
| int v = ep.parse(); | |
| visiting.erase(name); | |
| return v; | |
| } | |
| }; | |
| //============================================================== | |
| // Preprocessor | |
| //============================================================== | |
| class Preprocessor { | |
| public: | |
| explicit Preprocessor(Options opts = {}) : opts_(std::move(opts)) { | |
| // Treat empty include path as current directory | |
| if (opts_.include_path.empty()) { | |
| opts_.include_path = "."; | |
| } | |
| parseMacroDefinitions(opts_.macros); | |
| } | |
| std::string preprocess_file(const std::string & filename, const std::vector<std::string> & additional_macros = {}) { | |
| std::unordered_map<std::string, std::string> macros; | |
| std::unordered_set<std::string> predefined; | |
| std::unordered_set<std::string> include_stack; | |
| buildMacros(additional_macros, macros, predefined); | |
| std::string result = processFile(filename, macros, predefined, include_stack, DirectiveMode::All); | |
| return result; | |
| } | |
| std::string preprocess(const std::string & contents, const std::vector<std::string> & additional_macros = {}) { | |
| std::unordered_map<std::string, std::string> macros; | |
| std::unordered_set<std::string> predefined; | |
| std::unordered_set<std::string> include_stack; | |
| buildMacros(additional_macros, macros, predefined); | |
| std::string result = processString(contents, macros, predefined, include_stack, DirectiveMode::All); | |
| return result; | |
| } | |
| std::string preprocess_includes_file(const std::string & filename) { | |
| std::unordered_map<std::string, std::string> macros; | |
| std::unordered_set<std::string> predefined; | |
| std::unordered_set<std::string> include_stack; | |
| std::string result = processFile(filename, macros, predefined, include_stack, DirectiveMode::IncludesOnly); | |
| return result; | |
| } | |
| std::string preprocess_includes(const std::string & contents) { | |
| std::unordered_map<std::string, std::string> macros; | |
| std::unordered_set<std::string> predefined; | |
| std::unordered_set<std::string> include_stack; | |
| std::string result = processString(contents, macros, predefined, include_stack, DirectiveMode::IncludesOnly); | |
| return result; | |
| } | |
| private: | |
| Options opts_; | |
| std::unordered_map<std::string, std::string> global_macros; | |
| enum class DirectiveMode { All, IncludesOnly }; | |
| struct Cond { | |
| bool parent_active; | |
| bool active; | |
| bool taken; | |
| }; | |
| //---------------------------------------------------------- | |
| // Parse macro definitions into global_macros | |
| //---------------------------------------------------------- | |
| void parseMacroDefinitions(const std::vector<std::string> & macro_defs) { | |
| for (const auto & def : macro_defs) { | |
| size_t eq_pos = def.find('='); | |
| if (eq_pos != std::string::npos) { | |
| // Format: NAME=VALUE | |
| std::string name = trim(def.substr(0, eq_pos)); | |
| std::string value = trim(def.substr(eq_pos + 1)); | |
| global_macros[name] = value; | |
| } else { | |
| // Format: NAME | |
| std::string name = trim(def); | |
| global_macros[name] = ""; | |
| } | |
| } | |
| } | |
| //---------------------------------------------------------- | |
| // Build combined macro map and predefined set for a preprocessing operation | |
| //---------------------------------------------------------- | |
| void buildMacros(const std::vector<std::string> & additional_macros, | |
| std::unordered_map<std::string, std::string> & macros, | |
| std::unordered_set<std::string> & predefined) { | |
| macros = global_macros; | |
| predefined.clear(); | |
| for (const auto & [name, value] : global_macros) { | |
| predefined.insert(name); | |
| } | |
| for (const auto & def : additional_macros) { | |
| size_t eq_pos = def.find('='); | |
| std::string name, value; | |
| if (eq_pos != std::string::npos) { | |
| name = trim(def.substr(0, eq_pos)); | |
| value = trim(def.substr(eq_pos + 1)); | |
| } else { | |
| name = trim(def); | |
| value = ""; | |
| } | |
| // Add to macros map (will override global if same name) | |
| macros[name] = value; | |
| predefined.insert(name); | |
| } | |
| } | |
| //---------------------------------------------------------- | |
| // Helpers | |
| //---------------------------------------------------------- | |
| std::string loadFile(const std::string & fname) { | |
| std::ifstream f(fname); | |
| if (!f.is_open()) { | |
| throw std::runtime_error("Could not open file: " + fname); | |
| } | |
| std::stringstream ss; | |
| ss << f.rdbuf(); | |
| return ss.str(); | |
| } | |
| bool condActive(const std::vector<Cond> & cond) const { | |
| if (cond.empty()) { | |
| return true; | |
| } | |
| return cond.back().active; | |
| } | |
| //---------------------------------------------------------- | |
| // Process a file | |
| //---------------------------------------------------------- | |
| std::string processFile(const std::string & name, | |
| std::unordered_map<std::string, std::string> & macros, | |
| const std::unordered_set<std::string> & predefined_macros, | |
| std::unordered_set<std::string> & include_stack, | |
| DirectiveMode mode) { | |
| if (include_stack.count(name)) { | |
| throw std::runtime_error("Recursive include: " + name); | |
| } | |
| include_stack.insert(name); | |
| std::string shader_code = loadFile(name); | |
| std::string out = processString(shader_code, macros, predefined_macros, include_stack, mode); | |
| include_stack.erase(name); | |
| return out; | |
| } | |
| std::string processIncludeFile(const std::string & fname, | |
| std::unordered_map<std::string, std::string> & macros, | |
| const std::unordered_set<std::string> & predefined_macros, | |
| std::unordered_set<std::string> & include_stack, | |
| DirectiveMode mode) { | |
| std::string full_path = opts_.include_path + "/" + fname; | |
| return processFile(full_path, macros, predefined_macros, include_stack, mode); | |
| } | |
| //---------------------------------------------------------- | |
| // Process text | |
| //---------------------------------------------------------- | |
| std::string processString(const std::string & shader_code, | |
| std::unordered_map<std::string, std::string> & macros, | |
| const std::unordered_set<std::string> & predefined_macros, | |
| std::unordered_set<std::string> & include_stack, | |
| DirectiveMode mode) { | |
| std::vector<Cond> cond; // Conditional stack for this shader | |
| std::stringstream out; | |
| std::istringstream in(shader_code); | |
| std::string line; | |
| while (std::getline(in, line)) { | |
| std::string logical = line; | |
| std::string t = trim(logical); | |
| if (!t.empty() && t[0] == '#') { | |
| while (endsWithContinuation(logical)) { | |
| stripContinuation(logical); | |
| if (!std::getline(in, line)) { | |
| break; | |
| } | |
| logical += "\n"; | |
| logical += line; | |
| } | |
| t = trim(logical); | |
| } | |
| if (!t.empty() && t[0] == '#') { | |
| bool handled = handleDirective(t, out, macros, predefined_macros, cond, include_stack, mode); | |
| if (mode == DirectiveMode::IncludesOnly && !handled) { | |
| out << logical << "\n"; | |
| } | |
| } else { | |
| if (mode == DirectiveMode::IncludesOnly) { | |
| out << logical << "\n"; | |
| } else if (condActive(cond)) { | |
| // Expand macros in the line before outputting | |
| std::string expanded = expandMacrosRecursive(logical, macros); | |
| out << expanded << "\n"; | |
| } | |
| } | |
| } | |
| if (mode == DirectiveMode::All && !cond.empty()) { | |
| throw std::runtime_error("Unclosed #if directive"); | |
| } | |
| return out.str(); | |
| } | |
| //---------------------------------------------------------- | |
| // Directive handler | |
| //---------------------------------------------------------- | |
| bool handleDirective(const std::string & t, | |
| std::stringstream & out, | |
| std::unordered_map<std::string, std::string> & macros, | |
| const std::unordered_set<std::string> & predefined_macros, | |
| std::vector<Cond> & cond, | |
| std::unordered_set<std::string> & include_stack, | |
| DirectiveMode mode) { | |
| // split into tokens | |
| std::string body = t.substr(1); | |
| std::istringstream iss(body); | |
| std::string cmd; | |
| iss >> cmd; | |
| if (cmd == "include") { | |
| if (mode == DirectiveMode::All && !condActive(cond)) { | |
| return true; | |
| } | |
| std::string file; | |
| iss >> file; | |
| if (file.size() >= 2 && file.front() == '"' && file.back() == '"') { | |
| file = file.substr(1, file.size() - 2); | |
| } | |
| out << processIncludeFile(file, macros, predefined_macros, include_stack, mode); | |
| return true; | |
| } | |
| if (mode == DirectiveMode::IncludesOnly) { | |
| return false; | |
| } | |
| if (cmd == "define") { | |
| if (!condActive(cond)) { | |
| return true; | |
| } | |
| std::string name; | |
| iss >> name; | |
| // Don't override predefined macros from options | |
| if (predefined_macros.count(name)) { | |
| return true; | |
| } | |
| std::string value = trim_value(iss); | |
| macros[name] = value; | |
| return true; | |
| } | |
| if (cmd == "undef") { | |
| if (!condActive(cond)) { | |
| return true; | |
| } | |
| std::string name; | |
| iss >> name; | |
| // Don't undef predefined macros from options | |
| if (predefined_macros.count(name)) { | |
| return true; | |
| } | |
| macros.erase(name); | |
| return true; | |
| } | |
| if (cmd == "ifdef") { | |
| std::string name; | |
| iss >> name; | |
| bool p = condActive(cond); | |
| bool v = macros.count(name); | |
| cond.push_back({ p, p && v, p && v }); | |
| return true; | |
| } | |
| if (cmd == "ifndef") { | |
| std::string name; | |
| iss >> name; | |
| bool p = condActive(cond); | |
| bool v = !macros.count(name); | |
| cond.push_back({ p, p && v, p && v }); | |
| return true; | |
| } | |
| if (cmd == "if") { | |
| std::string expr = trim_value(iss); | |
| bool p = condActive(cond); | |
| bool v = false; | |
| if (p) { | |
| std::unordered_set<std::string> visiting; | |
| ExprParser ep(expr, macros, visiting); | |
| v = ep.parse() != 0; | |
| } | |
| cond.push_back({ p, p && v, p && v }); | |
| return true; | |
| } | |
| if (cmd == "elif") { | |
| std::string expr = trim_value(iss); | |
| if (cond.empty()) { | |
| throw std::runtime_error("#elif without #if"); | |
| } | |
| Cond & c = cond.back(); | |
| if (!c.parent_active) { | |
| c.active = false; | |
| return true; | |
| } | |
| if (c.taken) { | |
| c.active = false; | |
| return true; | |
| } | |
| std::unordered_set<std::string> visiting; | |
| ExprParser ep(expr, macros, visiting); | |
| bool v = ep.parse() != 0; | |
| c.active = v; | |
| if (v) { | |
| c.taken = true; | |
| } | |
| return true; | |
| } | |
| if (cmd == "else") { | |
| if (cond.empty()) { | |
| throw std::runtime_error("#else without #if"); | |
| } | |
| Cond & c = cond.back(); | |
| if (!c.parent_active) { | |
| c.active = false; | |
| return true; | |
| } | |
| if (c.taken) { | |
| c.active = false; | |
| } else { | |
| c.active = true; | |
| c.taken = true; | |
| } | |
| return true; | |
| } | |
| if (cmd == "endif") { | |
| if (cond.empty()) { | |
| throw std::runtime_error("#endif without #if"); | |
| } | |
| cond.pop_back(); | |
| return true; | |
| } | |
| // Unknown directive | |
| throw std::runtime_error("Unknown directive: #" + cmd); | |
| } | |
| }; | |
| } // namespace pre_wgsl | |