medit/moo/mooscript/mooscript-context.m

469 lines
8.3 KiB
Matlab
Raw Normal View History

2006-05-21 16:11:05 -07:00
/*
* mooscript-context.c
*
2007-06-24 10:56:20 -07:00
* Copyright (C) 2004-2007 by Yevgen Muntyan <muntyan@math.tamu.edu>
*
2007-06-24 10:56:20 -07:00
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* See COPYING file that comes with this distribution.
*/
2006-08-20 12:38:20 -07:00
#include "mooscript-context-private.h"
2006-05-14 16:45:13 -07:00
#include "mooscript-parser.h"
2006-08-20 12:38:20 -07:00
#include "mooscript-func-private.h"
2006-05-24 00:02:54 -07:00
#include "mooutils/moomarshals.h"
2007-07-12 03:12:15 -07:00
#include "mooutils/mooutils-misc.h"
#include <glib/gprintf.h>
2006-02-26 01:30:57 -08:00
#include <gtk/gtkwindow.h>
#define N_POS_VARS 20
2006-08-20 12:38:20 -07:00
typedef void (*MSPrintFunc) (const char *string,
MSContext *ctx);
struct _MSContextPrivate {
GHashTable *vars;
MSError error;
char *error_msg;
MSPrintFunc print_func;
2007-07-12 03:12:15 -07:00
gpointer window;
2006-08-20 12:38:20 -07:00
MSValue *return_val;
guint break_set : 1;
guint continue_set : 1;
guint return_set : 1;
2006-02-26 01:30:57 -08:00
};
2007-07-12 03:12:15 -07:00
@implementation MSContext : MooCObject
2006-05-19 22:09:09 -07:00
2006-02-26 01:30:57 -08:00
static void
2007-07-12 03:12:15 -07:00
default_print_func (const char *string,
G_GNUC_UNUSED MSContext *ctx)
2006-02-26 01:30:57 -08:00
{
2007-07-12 03:12:15 -07:00
g_print ("%s", string);
2006-02-26 01:30:57 -08:00
}
static void
2007-07-12 03:12:15 -07:00
variable_unref (MSVariable *var)
2006-02-26 01:30:57 -08:00
{
2007-07-12 03:12:15 -07:00
if (var)
[var release];
2006-02-26 01:30:57 -08:00
}
2007-07-12 03:12:15 -07:00
- init
{
2007-07-12 03:12:15 -07:00
[super init];
priv = _moo_new0 (MSContextPrivate);
priv->vars = g_hash_table_new_full (g_str_hash, g_str_equal, g_free,
(GDestroyNotify) variable_unref);
priv->print_func = default_print_func;
_ms_context_add_builtin (self);
return self;
}
2007-07-12 03:12:15 -07:00
- (void) dealloc
{
2007-07-12 03:12:15 -07:00
g_hash_table_destroy (priv->vars);
g_free (priv->error_msg);
ms_value_unref (priv->return_val);
_moo_free (MSContextPrivate, priv);
[super dealloc];
}
2007-07-12 03:12:15 -07:00
- (gpointer) window
{
2007-07-12 03:12:15 -07:00
return priv->window;
}
2007-07-12 03:12:15 -07:00
- (void) setWindow:(gpointer) window
{
2007-07-12 03:12:15 -07:00
priv->window = window;
}
2007-07-12 03:12:15 -07:00
+ (MSContext*) new:(gpointer) window
{
2007-07-12 03:12:15 -07:00
MSContext *ctx;
2006-03-07 23:10:49 -08:00
2007-07-12 03:12:15 -07:00
ctx = [[self alloc] init];
[ctx setWindow:window];
2006-05-24 00:02:54 -07:00
2007-07-12 03:12:15 -07:00
return ctx;
}
2007-07-12 03:12:15 -07:00
+ (MSContext*) new
{
return [self new:NULL];
}
2007-07-12 03:12:15 -07:00
+ initialize
{
2007-07-12 03:12:15 -07:00
ms_type_init ();
return self;
}
2007-07-12 03:12:15 -07:00
- (MSValue*) evalVariable:(CSTR) name
{
2006-02-24 20:39:12 -08:00
MSVariable *var;
g_return_val_if_fail (name != NULL, NULL);
2007-07-12 03:12:15 -07:00
var = [self lookupVar:name];
if (!var)
2007-07-12 03:12:15 -07:00
return [self formatError:MS_ERROR_NAME
:"no variable named '%s'",
name];
2007-07-12 03:12:15 -07:00
if ([var value])
return ms_value_ref ([var value]);
2007-07-12 03:12:15 -07:00
return [[var func] call:NULL :0 :self];
}
2007-07-12 03:12:15 -07:00
- (BOOL) assignVariable:(CSTR) name
:(MSValue*) value
{
2006-02-24 20:39:12 -08:00
MSVariable *var;
2007-07-12 03:12:15 -07:00
g_return_val_if_fail (name != NULL, NO);
2007-07-12 03:12:15 -07:00
var = [self lookupVar:name];
if (value)
{
if (var)
{
2007-07-12 03:12:15 -07:00
[var setValue:value];
}
else
{
2007-07-12 03:12:15 -07:00
var = [MSVariable new:value];
[self setVar:name :var];
[var release];
}
}
else if (var)
{
2007-07-12 03:12:15 -07:00
[self setVar:name :NULL];
}
2007-07-12 03:12:15 -07:00
return YES;
}
2007-07-12 03:12:15 -07:00
- (BOOL) assignPositional:(guint) n
:(MSValue*) value
{
char *name;
gboolean result;
name = g_strdup_printf ("_%u", n);
result = [self assignVariable:name :value];
2007-07-12 03:12:15 -07:00
g_free (name);
return result;
}
- (BOOL) assignString:(CSTR) name
:(CSTR) str_value
2006-04-19 11:06:05 -07:00
{
MSValue *value = NULL;
gboolean retval;
2007-07-12 03:12:15 -07:00
g_return_val_if_fail (name != NULL, NO);
2006-04-19 11:06:05 -07:00
if (str_value)
value = ms_value_string (str_value);
2007-07-12 03:12:15 -07:00
retval = [self assignVariable:name :value];
2006-04-19 11:06:05 -07:00
ms_value_unref (value);
return retval;
}
2007-07-12 03:12:15 -07:00
- (MSValue*) getEnvVariable:(CSTR) name
{
2007-07-12 03:12:15 -07:00
MOO_UNUSED_VAR (name);
return NULL;
}
2007-07-12 03:12:15 -07:00
- (BOOL) setVar:(CSTR) name
:(MSVariable*) var
{
2006-02-24 20:39:12 -08:00
MSVariable *old;
2007-07-12 03:12:15 -07:00
g_return_val_if_fail (name != NULL, NO);
2007-07-12 03:12:15 -07:00
old = g_hash_table_lookup (priv->vars, name);
if (var != old)
{
if (var)
2007-07-12 03:12:15 -07:00
g_hash_table_insert (priv->vars,
2006-08-20 12:38:20 -07:00
g_strdup (name),
2007-07-12 03:12:15 -07:00
[var retain]);
else
2007-07-12 03:12:15 -07:00
g_hash_table_remove (priv->vars, name);
}
2007-07-12 03:12:15 -07:00
return YES;
}
2007-07-12 03:12:15 -07:00
- (BOOL) setFunc:(CSTR) name
:(MSFunc*) func
{
2006-03-07 22:00:49 -08:00
MSValue *vfunc;
gboolean ret;
2007-07-12 03:12:15 -07:00
g_return_val_if_fail (name != NULL, NO);
2006-03-07 22:00:49 -08:00
vfunc = ms_value_func (func);
2007-07-12 03:12:15 -07:00
ret = [self assignVariable:name :vfunc];
2006-03-07 22:00:49 -08:00
ms_value_unref (vfunc);
2006-03-07 22:00:49 -08:00
return ret;
}
2007-07-12 03:12:15 -07:00
- (MSValue*) setError:(MSError) error
{
return [self setError:error :NULL];
}
- (MSValue*) setError:(MSError) error
:(CSTR) message
{
const char *errname;
2007-07-12 03:12:15 -07:00
g_return_val_if_fail (!priv->error && error, NULL);
g_return_val_if_fail (!priv->error_msg, NULL);
2007-07-12 03:12:15 -07:00
priv->error = error;
errname = [self getErrorMsg];
if (message && *message)
2007-07-12 03:12:15 -07:00
priv->error_msg = g_strdup_printf ("%s: %s", errname, message);
else
2007-07-12 03:12:15 -07:00
priv->error_msg = g_strdup (message);
return NULL;
}
2007-07-12 03:12:15 -07:00
- (MSValue*) formatError:(MSError) error
:(CSTR) format,
...
{
va_list args;
2006-03-14 14:27:40 -08:00
char *string;
2007-07-12 03:12:15 -07:00
g_return_val_if_fail (!priv->error && error, NULL);
g_return_val_if_fail (!priv->error_msg, NULL);
if (!format || !format[0])
2006-03-14 12:59:07 -08:00
{
2007-07-12 03:12:15 -07:00
[self setError:error :NULL];
2006-03-14 12:59:07 -08:00
return NULL;
}
va_start (args, format);
2006-08-20 12:38:20 -07:00
string = _ms_vaprintf (format, args);
va_end (args);
2007-07-12 03:12:15 -07:00
[self setError:error :string];
2006-03-14 14:27:40 -08:00
g_free (string);
return NULL;
}
2007-07-12 03:12:15 -07:00
- (CSTR) getErrorMsg
{
static const char *msgs[MS_ERROR_LAST] = {
NULL, "Type error", "Value error", "Name error",
"Runtime error"
};
2007-07-12 03:12:15 -07:00
g_return_val_if_fail (priv->error < MS_ERROR_LAST, NULL);
g_return_val_if_fail (priv->error != MS_ERROR_NONE, "ERROR");
2007-07-12 03:12:15 -07:00
if (priv->error_msg)
return priv->error_msg;
else
2007-07-12 03:12:15 -07:00
return msgs[priv->error];
}
2007-07-12 03:12:15 -07:00
- (void) clearError
{
2007-07-12 03:12:15 -07:00
priv->error = MS_ERROR_NONE;
g_free (priv->error_msg);
priv->error_msg = NULL;
}
2007-07-12 03:12:15 -07:00
@end
2007-07-12 03:12:15 -07:00
@implementation MSContext (MSContextPrivate)
2007-07-12 03:12:15 -07:00
- (MSVariable*) lookupVar:(CSTR)name
{
g_return_val_if_fail (name != NULL, NULL);
return g_hash_table_lookup (priv->vars, name);
}
2007-07-12 03:12:15 -07:00
- (void) setReturn:(MSValue*) val
{
2007-07-12 03:12:15 -07:00
g_return_if_fail (!priv->return_set);
priv->return_set = YES;
priv->return_val = val ? ms_value_ref (val) : ms_value_none ();
}
2007-07-12 03:12:15 -07:00
- (MSValue*) getReturn
{
2007-07-12 03:12:15 -07:00
g_return_val_if_fail (priv->return_set, NULL);
return ms_value_ref (priv->return_val);
}
2007-07-12 03:12:15 -07:00
- (void) unsetReturn
{
2007-07-12 03:12:15 -07:00
g_return_if_fail (priv->return_set);
priv->return_set = NO;
ms_value_unref (priv->return_val);
priv->return_val = NULL;
}
2007-07-12 03:12:15 -07:00
- (BOOL) returnSet
{
return priv->return_set;
}
2007-07-12 03:12:15 -07:00
- (void) setBreak
{
2007-07-12 03:12:15 -07:00
g_return_if_fail (!priv->break_set);
priv->break_set = YES;
2006-08-20 12:38:20 -07:00
}
2007-07-12 03:12:15 -07:00
- (void) setContinue
2006-08-20 12:38:20 -07:00
{
2007-07-12 03:12:15 -07:00
g_return_if_fail (!priv->continue_set);
priv->continue_set = YES;
}
2007-07-12 03:12:15 -07:00
- (void) unsetBreak
{
2007-07-12 03:12:15 -07:00
g_return_if_fail (priv->break_set);
priv->break_set = NO;
}
2007-07-12 03:12:15 -07:00
- (void) unsetContinue
{
2007-07-12 03:12:15 -07:00
g_return_if_fail (priv->continue_set);
priv->continue_set = NO;
}
2007-07-12 03:12:15 -07:00
- (BOOL) breakSet
{
2007-07-12 03:12:15 -07:00
return priv->break_set;
}
2007-07-12 03:12:15 -07:00
- (BOOL) continueSet
{
2007-07-12 03:12:15 -07:00
return priv->continue_set;
}
2007-07-12 03:12:15 -07:00
- (BOOL) errorSet;
{
2007-07-12 03:12:15 -07:00
return priv->error != 0;
2006-08-20 12:38:20 -07:00
}
2007-07-12 03:12:15 -07:00
- (void) print:(CSTR) string
2006-08-20 12:38:20 -07:00
{
2007-07-12 03:12:15 -07:00
priv->print_func (string, self);
2006-08-20 12:38:20 -07:00
}
2007-07-12 03:12:15 -07:00
@end
2006-08-20 12:38:20 -07:00
2007-07-12 03:12:15 -07:00
@implementation MSVariable : MooCObject
+ (MSVariable*) new:(MSValue*) value
2006-08-20 12:38:20 -07:00
{
2007-07-12 03:12:15 -07:00
MSVariable *var;
g_return_val_if_fail (value != NULL, nil);
var = [[self alloc] init];
var->value = ms_value_ref (value);
return var;
2006-08-20 12:38:20 -07:00
}
2007-07-12 03:12:15 -07:00
- (void) dealloc
2006-08-20 12:38:20 -07:00
{
2007-07-12 03:12:15 -07:00
if (value)
ms_value_unref (value);
if (func)
[func release];
[super dealloc];
}
2006-03-14 12:59:07 -08:00
2007-07-12 03:12:15 -07:00
- (void) setValue:(MSValue*) new_value
2006-05-14 16:45:13 -07:00
{
2007-07-12 03:12:15 -07:00
if (value != new_value)
{
if (value)
ms_value_unref (value);
if (new_value)
ms_value_ref (new_value);
2006-05-14 16:45:13 -07:00
2007-07-12 03:12:15 -07:00
value = new_value;
}
2006-05-14 16:45:13 -07:00
2007-07-12 03:12:15 -07:00
if (func)
{
[func release];
func = NULL;
}
2006-05-14 16:45:13 -07:00
}
2007-07-12 03:12:15 -07:00
- (void) setFunc:(MSFunc*) new_func
2006-05-24 00:02:54 -07:00
{
2007-07-12 03:12:15 -07:00
if (func != new_func)
{
if (func)
[func release];
if (new_func)
[new_func retain];
2006-05-24 00:02:54 -07:00
2007-07-12 03:12:15 -07:00
func = new_func;
}
2006-05-24 00:02:54 -07:00
2007-07-12 03:12:15 -07:00
if (value)
{
ms_value_unref (value);
value = NULL;
}
2006-05-24 00:02:54 -07:00
}
2006-08-20 12:38:20 -07:00
2007-07-12 03:12:15 -07:00
- (MSValue*) value
{
return value;
}
2006-08-20 12:38:20 -07:00
2007-07-12 03:12:15 -07:00
- (MSFunc*) func
2006-08-20 12:38:20 -07:00
{
2007-07-12 03:12:15 -07:00
return func;
2006-08-20 12:38:20 -07:00
}
2007-07-12 03:12:15 -07:00
@end
/* -*- objc -*- */