xassembler 0.5.1

Compiler tools for the xasm programming language
Documentation
use crate::{Compile, Identifier, Target, Value, MACHINE_NAME};

use alloc::string::{String, ToString};
use alloc::vec::Vec;

pub struct Golang;

impl Target for Golang {
    fn push(value: impl ToString) -> String {
        format!("{}.Push({})\n", MACHINE_NAME, value.to_string())
    }

    fn load(identifier: impl ToString) -> String {
        format!(
            "{name}{MACHINE}.Load()\n",
            MACHINE = MACHINE_NAME,
            name = identifier.to_string()
        )
    }

    fn number(number: impl ToString) -> String {
        format!("NewNumber({})", number.to_string())
    }

    fn string(string: impl ToString) -> String {
        format!("NewString({})", string.to_string())
    }

    fn store(value: impl ToString) -> String {
        format!("{}{}.Store()\n", value.to_string(), MACHINE_NAME)
    }

    fn copy(value: impl ToString) -> String {
        format!("{}{}.Copy()\n", value.to_string(), MACHINE_NAME)
    }

    fn block(body: impl ToString) -> String {
        format!(
            "NewFunction(func({MACHINE} *Machine) {{{}}}, MakeMachine())",
            body.to_string(),
            MACHINE = MACHINE_NAME
        )
    }

    fn func(body: impl ToString) -> String {
        format!(
            "NewFunction(func({MACHINE} *Machine) {{{func}}}, {MACHINE}.Duplicate())",
            func = body.to_string(),
            MACHINE = MACHINE_NAME
        )
    }

    fn foreign_func(name: impl ToString) -> String {
        format!(
            "NewFunction(Xasm_{name}, MakeMachine())",
            name = name.to_string(),
        )
    }

    fn for_loop(
        counter: impl ToString,
        element: impl ToString,
        list: impl ToString,
        body: impl ToString,
    ) -> String {
        format!(
            "{body}{list}{element}{counter}{MACHINE}.ForLoop()\n",
            MACHINE = MACHINE_NAME,
            counter = counter.to_string(),
            element = element.to_string(),
            list = list.to_string(),
            body = Self::push(Self::block(body))
        )
    }

    fn while_loop(condition: impl ToString, body: impl ToString) -> String {
        format!(
            "{body}{condition}{MACHINE}.WhileLoop()\n",
            MACHINE = MACHINE_NAME,
            condition = Self::push(Self::block(condition)),
            body = Self::push(Self::block(body))
        )
    }

    fn if_then_else(
        condition: impl ToString,
        then_fn: impl ToString,
        else_fn: impl ToString,
    ) -> String {
        format!(
            "{else_fn}{then_fn}{condition}{MACHINE}.IfThenElse()\n",
            MACHINE = MACHINE_NAME,
            condition = Self::push(Self::block(condition)),
            then_fn = Self::push(Self::block(then_fn)),
            else_fn = Self::push(Self::block(else_fn))
        )
    }

    fn call(func: impl ToString) -> String {
        format!(
            "{func}{MACHINE}.Call()\n",
            MACHINE = MACHINE_NAME,
            func = func.to_string()
        )
    }

    fn method_call(method_name: impl ToString) -> String {
        format!(
            "{method_name}{MACHINE}.MethodCall()\n",
            method_name = Self::push(method_name.to_string()),
            MACHINE = MACHINE_NAME
        )
    }

    fn assign(pointer_value: impl ToString) -> String {
        format!(
            "{pointer_value}{MACHINE}.Assign()\n",
            pointer_value = pointer_value.to_string(),
            MACHINE = MACHINE_NAME
        )
    }

    fn dotname(head: Value, tail: Vec<Identifier>) -> String {
        let mut result = Compile::<Self>::compile(head).unwrap();
        for ident in tail {
            let Identifier(name) = ident;
            result += &(Self::push(Self::string(Self::quote(name)))
                + &format!("{}.Index()\n", MACHINE_NAME));
        }
        result
    }

    fn indexname(head: Value, tail: Vec<Value>) -> String {
        let mut result = Compile::<Self>::compile(head).unwrap();
        for value in tail {
            result += &(Compile::<Self>::compile(value).unwrap()
                + &format!("{}.Index()\n", MACHINE_NAME));
        }
        result
    }
}