eval - eval

редактировать

В некоторых языках программирования, eval- это функция, которая вычисляет строка, как если бы это было выражение, и возвращает результат ; в других случаях он выполняет несколько строк кода, как если бы они были включены вместо строки, включающей eval. Ввод в evalне обязательно является строкой; это может быть структурированное представление кода, такое как абстрактное синтаксическое дерево (например, формы Lisp ), или специального типа, например code(как в Python). Аналогом для оператора является exec, который выполняет строку (или код в другом формате), как если бы это был оператор; в некоторых языках, таких как Python, присутствуют оба, в то время как в других языках есть только один из evalили exec.

Eval и apply - это экземпляры мета-циклических вычислителей, интерпретаторов языка, которые могут быть вызваны внутри самого языка.

Содержание
  • 1 Угрозы безопасности
  • 2 Реализация
  • 3 Языки программирования
    • 3.1 ECMAScript
      • 3.1.1 JavaScript
      • 3.1.2 ActionScript
    • 3.2 Lisp
    • 3.3 Perl
    • 3.4 PHP
    • 3.5 Lua
    • 3.6 PostScript
    • 3.7 Python
    • 3.8 D
    • 3.9 ColdFusion
    • 3.10 Ruby
    • 3.11 Forth
    • 3.12 BASIC
      • 3.12. 1 REALbasic
      • 3.12.2 VBScript
      • 3.12.3 Visual Basic для приложений
    • 3.13 Smalltalk
    • 3.14 Tcl
    • 3.15 bs
  • 4 Интерпретаторы командной строки
    • 4.1 Оболочки Unix
    • 4.2 Windows PowerShell
  • 5 Микрокод
  • 6 Теория
  • 7 Ссылки
  • 8 Внешние ссылки
Угрозы безопасности

Использование evalс данными из ненадежного источника может привести к уязвимостям безопасности. Например, если предположить, что функция get_data ()получает данные из Интернета, этот код Python небезопасен:

session ['authenticated'] = False data = get_data () foo = eval (data)

Злоумышленник может предоставить программе строку "session.update (authenticated = True)"в качестве данных, которые обновят словарь session, чтобы установить для аутентифицированного ключа значение True. Чтобы исправить это, все данные, которые будут использоваться с eval, должны быть экранированы, или они должны выполняться без доступа к потенциально опасным функциям.

Реализация

В интерпретируемых языках, evalпочти всегда реализуется с тем же интерпретатором, что и обычный код. В скомпилированных языках тот же компилятор, который использовался для компиляции программ, может быть встроен в программы с помощью функции eval; иногда используются отдельные интерпретаторы, хотя это приводит к дублированию кода.

Языки программирования

ECMAScript

JavaScript

В JavaScript, eval- это что-то вроде гибрида между оценщиком выражений и исполнителем операторов. Он возвращает результат последнего вычисленного выражения.

Пример в качестве средства оценки выражения:

foo = 2; предупреждение (eval ('foo + 2'));

Пример в качестве исполнителя оператора:

foo = 2; eval ('foo = foo + 2; alert (foo);');

Одно из применений JavaScript eval- анализировать текст JSON, возможно, как часть структуры Ajax. Однако современные браузеры предоставляют JSON.parseкак более безопасную альтернативу для этой задачи.

ActionScript

В ActionScript (язык программирования Flash) evalне может использоваться для оценки произвольных выражений. Согласно документации Flash 8, его использование ограничено выражениями, которые представляют «имя переменной, свойства, объекта или фрагмента ролика для извлечения. Этот параметр может быть либо строкой, либо прямой ссылкой на экземпляр объекта».

ActionScript 3 не поддерживает eval.

Библиотека ActionScript 3 Eval и API D.eval являются текущими проектами разработки по созданию эквивалентов evalв ActionScript 3.

Lisp

Lisp был исходным языком, в котором в 1958 году использовалась функция eval. Фактически, определение функции evalпривело к первой реализации интерпретатора языка. До того, как была определена функция eval, функции Lisp вручную компилировались в операторы языка ассемблера. Однако, как только функция evalбыла скомпилирована вручную, она использовалась как часть простого цикла чтение-оценка-печать, который лег в основу первого интерпретатора Лиспа.

Более поздние версии функции Lisp evalтакже были реализованы как компиляторы.

Функция evalв Лиспе ожидает, что форма будет вычислена и выполнена как аргумент. Возвращаемое значение данной формы будет значением, возвращаемым вызовом eval.

Это пример кода Лиспа:

; Форма, которая вызывает функцию + с аргументами 1,2 и 3. ; Возвращает 6. (+ 1 2 3); Следовательно, в lisp любая форма предназначена для оценки; звонок в + был выполнен. ; Мы можем запретить Lisp выполнять оценку; формы, добавив к ней префикс "'", например: (setq form1' (+ 1 2 3)); Теперь form1 содержит форму, которую может использовать eval для; пример: (eval form1); eval вычислил (+ 1 2 3) и вернул 6.

Lisp, как и функция eval, хорошо известен как очень гибкий. Например, чтобы оценить содержимое строки, строку сначала нужно преобразовать в форму Лиспа с помощью функции read-from-string, а затем полученную форму нужно передать в eval:

(eval (read-from-string "(формат t \" Hello World !!! ~% \ ")"))

Одной из основных проблем является вопрос, в каком контексте символы в форма будет оценена. В приведенном выше примере form1содержит символ +. Оценка этого символа должна дать функцию сложения, чтобы пример работал должным образом. Таким образом, некоторые диалекты lisp позволяют использовать дополнительный параметр для eval, чтобы указать контекст оценки (аналогично необязательным аргументам функции Python eval- см. Ниже). Пример на диалекте Scheme Лиспа (RRS и новее):

;; Определите простую форму, как в приведенном выше примере. (определить form2 '(+ 5 2)); Значение: form2 ;; Оцените форму в исходном контексте. ;; Контекст для оценки называется на сленге Scheme «средой». (eval form2 user-initial-environment); Значение: 7 ;; Запутайте исходное окружение, так что + будет ;; имя функции вычитания. (environment-define-user-initial-environment '+ -); Значение: + ;; Оцените форму еще раз. ;; Обратите внимание, что возвращаемое значение изменилось. (eval form2 user-initial-environment); Значение: 3

Perl

В Perl функция evalпредставляет собой нечто среднее между вычислителем выражений и исполнитель выписки. Он возвращает результат последнего вычисленного выражения (все операторы являются выражениями в программировании на Perl) и позволяет не ставить последнюю точку с запятой.

Пример в качестве средства оценки выражения:

$ foo = 2; напечатать eval ('$ foo + 2'), "\ n";

Пример в качестве исполнителя оператора:

$ foo = 2; eval ('$ foo + = 2; print "$ foo \ n";');

Perl также имеет блоки eval, которые служат его механизмом обработки исключений (см. синтаксис обработки исключений # Perl ). Это отличается от вышеупомянутого использования evalсо строками тем, что код внутри блоков evalинтерпретируется во время компиляции, а не во время выполнения, поэтому это не значение eval, использованный в этой статье.

PHP

В PHP, evalвыполняет код в строке почти так же, как если бы он был помещен в файл, вместо вызова eval (). Единственное исключение состоит в том, что ошибки сообщаются как возникшие в результате вызова eval (), а операторы return становятся результатом функции.

В отличие от некоторых языков, аргумент evalдолжен быть строкой из одного или нескольких полных операторов, а не только выражений; однако можно получить форму «выражения» eval, поместив выражение в оператор return, который заставляет evalвозвращать результат этого выражения.

В отличие от некоторых языков, PHP evalпредставляет собой "языковую конструкцию", а не функцию, и поэтому не может использоваться в некоторых контекстах, где могут быть функции, например, функции высшего порядка.

Пример использования echo:

Пример возврата значения:

Lua

В Lua 5.1, loadstringкомпилирует код Lua в анонимная функция.

Пример в качестве средства оценки выражения:

loadstring ("print ('Hello World!')") ()

Пример выполнения оценки в два этапа:

a = 1 f = loadstring ("return a + 1") - скомпилировать выражение в анонимную функцию print (f ()) - выполнить (и вывести результат '2')

Lua 5.2 не поддерживает loadstringв предпочтение существующей функции load, которая была расширена для приема строк. Кроме того, он позволяет напрямую предоставлять среду функции, так как среды теперь имеют upvalues ​​.

print (load ("print ('Hello'.. a)", "", "t", {a = "World ! ", print = print}) ())

PostScript

Оператор PostScript execпринимает операнд - если это простой литерал, он помещает его обратно в стек. Однако, если взять строку, содержащую выражение PostScript, можно преобразовать строку в исполняемый файл, который затем может быть выполнен интерпретатором, например:

((Hello World) =) cvx exec

преобразовывает выражение PostScript

(Hello World) =

, который извлекает строку «Hello World» из стека и отображает ее на экране, чтобы иметь исполняемый тип, а затем выполняется.

Оператор PostScript runаналогичен по функциональности, но вместо этого интерпретатор сам интерпретирует выражения PostScript в файле.

(file.ps) run

Python

В Python функция evalв своей простейшей форме оценивает одно выражение.

evalпример (интерактивная оболочка):

>>>x = 1>>>eval ('x + 1') 2>>>eval ('x') 1

The Функция evalпринимает два необязательных аргумента, globalи locals, которые позволяют программисту установить ограниченную среду для оценки выражения.

Оператор exec(или функция execв Python 3.x) выполняет операторы:

Пример exec(интерактивная оболочка):

>>>x = 1>>>y = 1>>>exec "x + = 1; y - = 1">>>x 2>>>y 0

Самая общая форма для оценки операторов / выражений использует объекты кода. Их можно создать, вызвав функцию compile ()и сообщив ей, какой тип ввода она должна скомпилировать: оператор «exec», «eval <85.>"или" single":

пример компиляции(интерактивная оболочка):

>>>x = 1>>>y = 2>>>eval (compile ("print 'x + y =', x + y", "compile-sample.py", "single")) x + y = 3

D

D является статически компилируемым языком и поэтому не включает "eval"в традиционном смысле, но включает связанный оператор" mixin". Разница в том, что, где «eval» интерпретирует строку как код во время выполнения, с «mixin» строка статически компилируется как обычный код и должна быть известна во время компиляции. Например:

import std.stdio; void main () {int num = 0; миксин ("число ++;"); Writeln (число); // Выводит 1.}

Приведенный выше пример будет компилироваться с точно такими же инструкциями на ассемблере, как если бы "num ++;" было написано напрямую, а не смешано. Аргумент для mixin не нужен быть строковым литералом, но произвольные выражения, приводящие к строковому значению, включая вызовы функций, которые могут быть вычислены во время компиляции.

ColdFusion

Функция calculateв ColdFusion позволяет оценивать строковое выражение во время выполнения.

Это особенно полезно, когда вам нужно программно выбрать переменную, из которой вы хотите читать.

Ruby

Интерпретатор языка программирования Ruby предлагает функцию eval, аналогичную Python или Perl, а также допускает область видимости или привязка, подлежит уточнению.

Помимо указания привязки функции, evalтакже может использоваться для оценки выражения в конкретной привязке определения класса или привязки экземпляра объекта, что позволяет расширять классы с помощью новых методов, указанных в строках.

a = 1 eval ('a + 1') # (оценивается как 2) # оценка в контексте def get_binding (a) привязка end eval ('a + 1', get_binding (3)) # (оценивается как 4, потому что "a" в контексте get_binding равно 3)
class Test; end Test.class_eval ("def hello; return 'hello'; end") # добавить метод 'hello' к этому классу Test.new.hello # оценивается как "hello"

Forth

Самый стандартный реализации Forth имеют два варианта eval: EVALUATEи INTERPRET.

Пример кода Win32FORTH:

S "2 2 +". EVALUATE \ Outputs "4"

BASIC

REALbasic

В REALbasic есть класс с именем RBScript, который может выполнять код REALbasic на время выполнения. RBScript очень изолирован - там только самые основные языковые функции, и вы должны предоставить ему доступ к тому, что вы хотите. При желании вы можете назначить объект свойству контекста. Это позволяет коду в RBScript вызывать функции и использовать свойства объекта контекста. Однако он по-прежнему ограничен пониманием только самых основных типов, поэтому, если у вас есть функция, возвращающая Dictionary или MySpiffyObject, RBScript не сможет ее использовать. Вы также можете общаться со своим RBScript через события Print и Input.

VBScript

Microsoft VBScript, который является интерпретируемым языком, имеет две конструкции. Eval- это средство оценки функции, которое может включать вызовы пользовательских функций. (Эти функции могут иметь побочные эффекты, такие как изменение значений глобальных переменных.) Executeвыполняет один или несколько операторов, разделенных двоеточиями, которые могут изменять глобальное состояние.

И VBScript, и JScript evalдоступны разработчикам скомпилированных приложений Windows (написанных на языках, не поддерживающих Eval) через элемент управления ActiveX, называемый Microsoft Script Control, чей метод Eval может быть вызывается кодом приложения. Для поддержки вызова пользовательских функций необходимо сначала инициализировать элемент управления с помощью метода AddCode, который загружает строку (или строковый ресурс), содержащую библиотеку пользовательских функций, определенных на выбранном вами языке, перед вызовом Eval..

Visual Basic для приложений

Visual Basic для приложений (VBA), язык программирования Microsoft Office, представляет собой язык виртуальных машин, на котором среда выполнения компилируется и запускается p-code. Его разновидность Eval поддерживает только оценку выражения, где выражение может включать определяемые пользователем функции и объекты (но не определяемые пользователем имена переменных). Следует отметить, что оценщик отличается от VBS, и вызов определенных пользовательских функций может работать в VBA иначе, чем идентичный код в VBScript.

Smalltalk

Поскольку классы компилятора Smalltalk являются частью стандартной библиотеки классов и обычно присутствуют во время выполнения, их можно использовать для оценки строки кода.

Оценка компилятора: '1 + 2'

Поскольку определения классов и методов также реализуются посредством отправки сообщений (в объекты класса), возможны даже изменения кода:

Оценка компилятора: 'Подкласс объекта: #Foo '

Tcl

В языке программирования Tcl есть команда с именем eval, которая выполняет исходный код, предоставленный в качестве аргумента. Tcl представляет весь исходный код в виде строк с фигурными скобками, действующими как кавычки, так что аргумент evalможет иметь такое же форматирование, как и любой другой исходный код.

set foo {в то время как {[incr i] <10} { puts "$i squared is [expr $i*$i]" } } eval $foo

bs

bs имеет функцию eval, которая принимает один строковый аргумент. Функция является одновременно оценщиком выражений и исполнителем операторов. В последней роли он также может использоваться для обработки ошибок. Следующие примеры и текст взяты из bsсправочной страницы, как показано в Руководстве программиста UNIX System V версии 3.2.

Строковый аргумент оценивается как bsвыражение. Функция удобна для преобразования числовых строк во внутреннюю числовую форму. evalтакже может использоваться как грубая форма косвенного обращения, как показано ниже (обратите внимание, что в bs, _(подчеркивание) находится оператор конкатенации.):

name = "xyz" eval ("++" _ name)

, который увеличивает переменную xyz.

. Кроме того, eval, которому предшествует оператор запроса, ?, позволяет пользователю control bsусловия ошибки. Например:

? Eval ("open (\" X \ ", \" XXX \ ", \" r \ ")")

возвращает нулевое значение, если нет файла с именем "XXX" (вместо этого остановки программы пользователя).

Следующий код выполняет gotoк метке L(если он существует):

label = "L" if! (? Eval ("goto" _ label)) puterr = "no label"
Интерпретаторы командной строки

оболочки Unix

Команда eval присутствует во всех оболочках Unix, включая исходную "ш" (панцирь Борна ). Он объединяет все аргументы с пробелами, затем повторно анализирует и выполняет результат как команду. sh (1) FreeBSD Общие команды Руководство

Windows PowerShell

В Windows PowerShell Invoke- Командлет Expressionслужит той же цели, что и функция eval в таких языках программирования, как JavaScript, PHP и Python. Командлет запускает любое выражение Windows PowerShell, которое предоставляется как параметр команды в виде строки, и выводит результат указанного выражения. Обычно выходные данные командлета имеют тот же тип, что и результат выполнения выражения. Однако, если результатом является пустой массив, он выводит $ null. Если результатом является одноэлементный массив, он выводит этот единственный элемент. Подобно JavaScript, Windows PowerShell позволяет опускать последнюю точку с запятой.

Пример в качестве средства оценки выражения:

PS>$ foo = 2 PS>invoke-expression '$ foo + 2'

Пример в качестве исполнителя оператора:

PS>$ foo = 2 PS>выражение-вызов '$ foo + = 2; $ foo '
Микрокод

В 1966 году IBM Система диалогового программирования (CPS) представила микропрограммированную функцию EVALдля выполнения «интерпретирующей оценки выражений, записанных в модифицированной нотации польской строки » в IBM System / 360 Model 50. Микрокодирование этой функции было «существенно больше» более чем в пять раз по сравнению с программой, которая интерпретировала утверждение присвоение.

Теория

В теоретической информатике, обычно проводится четкое различие между eval и apply. Под Eval понимается этап преобразования строки в кавычках в вызываемую функцию и ее аргументы, тогда как apply - это фактический вызов функции с заданным набором аргументов. Это различие особенно заметно в функциональных языках и языках, основанных на лямбда-исчислении, таких как LISP и Scheme. Таким образом, например, в схеме различают

(eval '(fx))

, где должна быть оценена форма (fx), и

(apply f (list x))

где функция f должна вызываться с аргументом x.

Eval и apply - два взаимозависимых компонента цикла eval-apply, который является сутью оценки Lisp, описанного в SICP.

В теории категорий eval морфизм используется для определения закрытой моноидальной категории. Так, например, категория наборов с функциями, взятыми как морфизмы, и декартово произведение, принятое как произведение, образует декартово замкнутое категория. Здесь eval (или, собственно говоря, apply ) вместе с его правым сопряженным , currying, образуют просто типизированное лямбда-исчисление, которые можно интерпретировать как морфизмы декартовых замкнутых категорий.

Ссылки
Внешние ссылки
Последняя правка сделана 2021-05-19 08:16:40
Содержание доступно по лицензии CC BY-SA 3.0 (если не указано иное).
Обратная связь: support@alphapedia.ru
Соглашение
О проекте