endbasic-core 0.13.0

The EndBASIC programming language - core
Documentation
// EndBASIC
// Copyright 2026 Julio Merino
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.

//! A callable exposed to integration tests.

use endbasic_core::*;
use std::borrow::Cow;
use std::io;
use std::rc::Rc;

/// A function that raises an error based on a string argument.
///
/// The first argument is a keyword that determines the error type.  When the
/// keyword is `"syntax"`, `"syntax0"`, or `"syntax1"`, the error is a
/// `CallError::Syntax` with the position overridden to point at the string
/// argument, the first argument, or the second argument respectively.  This
/// lets integration tests verify that the VM correctly propagates the position
/// override from `CallError::Syntax`.
pub(super) struct RaisefFunction {
    metadata: Rc<CallableMetadata>,
}

impl RaisefFunction {
    pub(super) fn new() -> Rc<Self> {
        Rc::from(Self {
            metadata: CallableMetadataBuilder::new("RAISEF")
                .with_return_type(ExprType::Boolean)
                .with_syntax(&[
                    (
                        &[SingularArgSyntax::RequiredValue(
                            RequiredValueSyntax {
                                name: Cow::Borrowed("arg"),
                                vtype: ExprType::Text,
                            },
                            ArgSepSyntax::End,
                        )],
                        None,
                    ),
                    (
                        &[
                            SingularArgSyntax::RequiredValue(
                                RequiredValueSyntax {
                                    name: Cow::Borrowed("arg"),
                                    vtype: ExprType::Text,
                                },
                                ArgSepSyntax::Exactly(ArgSep::Long),
                            ),
                            SingularArgSyntax::RequiredValue(
                                RequiredValueSyntax {
                                    name: Cow::Borrowed("n"),
                                    vtype: ExprType::Integer,
                                },
                                ArgSepSyntax::End,
                            ),
                        ],
                        None,
                    ),
                ])
                .test_build(),
        })
    }
}

impl Callable for RaisefFunction {
    fn metadata(&self) -> Rc<CallableMetadata> {
        self.metadata.clone()
    }

    fn exec(&self, scope: Scope<'_>) -> CallResult<()> {
        let arg = scope.get_string(0);
        match arg {
            "argument" => Err(CallError::Argument("Bad argument".to_owned())),
            "eval" => Err(CallError::Eval("Some eval error".to_owned())),
            "internal" => Err(CallError::Eval("Some internal error".to_owned())),
            "io" => Err(CallError::from(io::Error::other("Some I/O error"))),
            "syntax" => Err(CallError::Syntax(scope.get_pos(0), "Some syntax error".to_owned())),
            "syntax0" => Err(CallError::Syntax(scope.get_pos(0), "Some syntax error".to_owned())),
            "syntax1" => Err(CallError::Syntax(scope.get_pos(1), "Some syntax error".to_owned())),
            _ => Err(CallError::Argument("Invalid arguments".to_owned())),
        }
    }
}